C++: как иметь дело с объектом константы что потребности, которые будут изменены?

@Brian R. Bondy указал на меня на интересную статью о Сокрытии посредством наследования и новый ключевое слово.

http://msdn.microsoft.com/en-us/library/aa691135 (По сравнению с 71) .aspx

Поэтому как обходное решение я предложил бы:

class BaseClass
{
    public void A()
    {
        Console.WriteLine("BaseClass.A");
    }

    public void B()
    {
        Console.WriteLine("BaseClass.B");
    }
}

class DerivedClass : BaseClass
{
    new public void A()
    {
        throw new NotSupportedException();
    }

    new public void B()
    {
        throw new NotSupportedException();
    }

    public void C()
    {
        base.A();
        base.B();
    }
}

Этот путь код как это бросит NotSupportedException:

    DerivedClass d = new DerivedClass();
    d.A();

6
задан V_D_R 15 October 2009 в 14:04
поделиться

7 ответов

Я бы не стал использовать решения const_cast, и копирование объекта может не сработать. Вместо этого, почему бы не присвоить условно другую ссылку на константу? Если myVar действителен, назначьте это. Если нет, назначьте значение по умолчанию. Затем в приведенном ниже коде можно использовать эту новую ссылку на константу. Один из способов сделать это - использовать условное выражение:

const myType& myOtherVar = (myVar.isValid() ? myVar : defaultVar);

Другой способ - написать функцию, которая принимает константную ссылку (myVar) и возвращает myVar или defaultVar, в зависимости от действительности myVar, и присваивает возвращаемое значение из это в myOtherVar.

Третий способ - использовать константный указатель, указывая его либо на адрес myVar, либо на адрес объекта по умолчанию.

5
ответ дан 8 December 2019 в 14:44
поделиться
const_cast<type without const>()

Но действительно ли someMethod () возвращает const myType ? Если это так, вы делаете ссылку на временную - она ​​будет уничтожена, а ваша ссылка будет плохой. Измените myVar на non-ref (чтобы он копировал) - в этом случае не нужно объявлять его const. Или, если someMethod () возвращает ссылку, используйте const_cast , если необходимо (но вы меняете то, что, по мнению someMethod , не изменится).

1
ответ дан 8 December 2019 в 14:44
поделиться

Попробуйте следующее

myType& mutableMyVar = const_cast<myType&>(myVar);

В общем, удаление const - плохая идея. Метод вызывающего объекта вернул вам ссылку на переменную, которая, по его мнению, будет рассматриваться как const. Если вы нарушите это предположение, удалив константу и изменив переменную, вы можете перевести любой объект в допустимое состояние.

Это может быть законным в вашем конкретном случае, но в целом этого следует избегать

0
ответ дан 8 December 2019 в 14:44
поделиться

Вы можете создать объект из константного объекта, используя конструктор копирования или какой-то другой оператор присваивания, а затем изменить его.

Но я думаю, вам лучше понять, почему функция возвращает константный тип на первом месте. Была причина, по которой он был объявлен как const. Если вы абсолютно уверены, что это именно то, что вам нужно, вы всегда можете использовать const_cast для исключения константности следующим образом:

T obj1 = const_cast<T&> (obj); 
0
ответ дан 8 December 2019 в 14:44
поделиться

Скорее всего, вам не понадобится приведение. Если вы можете скопировать T , то вы также можете скопировать T const , за исключением патологических случаев. Копия T const не обязательно должна быть самой T const .

myType myVar = someMethod(); // Creates a non-const copy that you may change.
9
ответ дан 8 December 2019 в 14:44
поделиться

Каков "правильный" способ C ++ делать это преобразование константы в неконстантное? Статический бросок? Лексический состав? Что-нибудь еще?

С ++ не существует. По той или иной причине автор этого класса решил, что вы не должны иметь возможность изменять экземпляр с помощью этого метода.

Если бы вы были автором, вы могли бы заставить его возвращать неконстантную ссылку. Но они по-прежнему вызывают подозрение, если только классу действительно не нужно скрывать его от вас (например, как вектор не скрывает то, что он держит для вас, а просто скрывает то, как он что-то держит. для вас).

Лучшим способом (в зависимости от того, о чем идет речь) также может быть не открывать члены для внешних манипуляций, а предоставить метод, который выполняет эти манипуляции за вас. Например:

class BadPosition
{
    int x, y;
 public:
    int& get_x() { return x; }
    int& get_y() { return x; }
    //...
};

BadPosition p;
p.get_x() += 1;
p.get_y() += -1;

class BetterPosition
{
    int x, y;
 public:
    void move(int x_inc, int y_inc) { x += x_inc; y += y_inc; }
    //...
};

BetterPosition p;
p.move(1, -1);

Если вам это нужно, чтобы позже перевести класс в допустимое состояние, возможно, подумайте о том, чтобы сделать это его конструктором. Если вы не можете этого сделать, по крайней мере, предоставьте метод Init (), чтобы не делать такой сложный класс полностью зависимым от внешнего управления и превращения его во что-то полезное.

Конечно, могут быть и другие способы, не требующие преобразования, например вы можете создать копию, изменить ее, а затем использовать измененную копию для замены всего экземпляра другим (при условии, что этого достаточно для его создания):

X x;
...
Y y = x.get();
y.modify();
x = X(y);

Изменить: Итак, класс возвращается по значению? В этом случае не должно быть возможности изменить экземпляр в классе, поскольку все, что вы получаете, - это в первую очередь его копию. Вы можете ссылаться на это с помощью константной ссылки, но даже если вы откажетесь от константности из этой ссылки, вы все равно будете ссылаться на временную.

0
ответ дан 8 December 2019 в 14:44
поделиться

Нет способа "C ++" (не только для этого, но и для чего-либо).

Плохой способ - использовать const_cast , но тогда поведение будет быть неопределенным (читайте: не делайте этого)

Что вам нужно сделать, так это скопировать объект, а затем изменить копию. Это единственный правильный способ работы с неизменяемыми объектами.

1
ответ дан 8 December 2019 в 14:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: