Проблема виртуального класса - PullRequest
0 голосов
/ 02 мая 2010

Что я думаю о виртуальном классе, так это то, что если производный класс имеет общедоступную базу, скажем, базу классов, то указатель на производный может быть присвоен переменной типа указатель на базу без использования какого-либо явного преобразования типа. Но что если мы находимся внутри базового класса, то как мы можем вызывать функции производного класса. Я приведу пример:

class Graph{
  public:
    Graph(string);
    virtual bool addEdge(string,string);
}
class Direct:public Graph{
  public:  
    Direct(string);
    bool addEdge(string,string);
}
Direct::Direct(string filename):Graph(filename){};

Когда я вызываю конструктор класса Direct, он вызывает Graph. Теперь давайте подумаем, что функция Graph добавила вызовы.

Graph(string str){
    addedge(str,str);
}

Когда он вызывает addge, даже если функция виртуальная, он вызывает Graph :: edge. То, что я хочу, это вызвать Direct :: addge. Как это можно сделать?

Ответы [ 4 ]

3 голосов
/ 02 мая 2010

Это не может быть сделано. Виртуальные функции нельзя вызывать в конструкторах - по крайней мере, их нельзя вызывать с виртуальным поведением. Проблема заключается в том, что конструктор производного класса отвечает за настройку vtbl для указания на его конкретный экземпляр виртуальных функций. Конструктор базового класса выполняется первым, перед производным конструктором, поэтому прямое решение этого невозможно.

Вы можете обойти это, используя какую-либо функцию "init" в вашем базовом классе, или вы можете использовать фабричный метод.

2 голосов
/ 02 мая 2010

Это по проекту в C ++, см. C ++ FAQ .

В вашем случае я также не понимаю, зачем вам это нужно - если вы хотите использовать вспомогательную функцию инициализации, вам не нужно, чтобы она была виртуальной.

1 голос
/ 02 мая 2010

Ваше объяснение здесь в Скотте Мейере Эффективное C ++

Не вызывайте виртуальные функции во время создания или уничтожения, потому что такие вызовы никогда не перейдут к более производному классу, чем класс выполняемого в данный момент конструктора или деструктора.

0 голосов
/ 02 мая 2010

Похоже, вы хотите, чтобы конструктор базового типа вызывал производный тип через виртуальный метод. Это хлопотно, поскольку производный тип еще не полностью создан. Что переопределенная виртуальная функция производного типа собирается использовать для состояния, когда ее тип еще не создан? Возможно, вы захотите изучить другой шаблон проектирования, например фабрику, который может инкапсулировать двухэтапный шаблон построения / инициализации, если он вам действительно нужен.

...