2014-10-31 3 views
2

Есть ли способ под C++ иметь наследование объектов наследования, действующее как наследование конструкторов? Давайте следующее:Наследование наследования конструкторов против наследования методов в объектах C++

(myclass.h) 

class B{ 
public: 
    B(); 

    void doSomething(); 
}; 

class A : public B{ 
public: 
    A(); 

    void doSomething(); 
} 

(myclass.cpp) 

B::B() 
{ 
    executeBCode(); 
} 

void B::doSomething() 
{ 
    executeBCode(); 
} 

A::A : B() 
{ 
    executeACode(); 
} 

void A::doSomething() 
{ 
    executeACode(); 
} 

Что происходит, что вызов конструктора, я исполню executeBCode() и затем executeACode(). С вызовом метода doSomething() на объекте я выполняю только executeACode(), потому что он переопределен. Есть ли способ наследования методов, которые ведут себя как наследование на конструкторах, поэтому выполняют как производный, так и базовый код? Я пришел к этому вопросу, потому что мне нужно, чтобы базовый класс в моем коде делал что-то для его производного класса, и, кроме того, производный должен выполнять свои собственные инструкции: это просто вызывает функцию doSomething() на производном. Это может быть случай метода closeAll(), называемого A, например, где базовый класс закрывает свои собственные базовые объекты и выводит их конкретные вещи.

+2

Вы можете просто добавить вызов 'B :: doSomething();' в функцию 'void A :: doSomething()'. Еще раз исследуем шаблон шаблона шаблона (http://en.wikipedia.org/wiki/Template_method_pattern). – Niall

+0

Вызов 'B :: doSomething();' on A означает, что наследование бесполезно. Я не могу игнорировать, почему он не был реализован на языке C++ с ключевым словом в базовом методе. И, возможно, на других языках программирования тоже ... – ABCplus

+1

'doSomething' не переопределяется, он просто скрыт другой функцией с тем же именем. Переопределение означает замену виртуальной функции, и у вас нет виртуальных функций. –

ответ

0

Не существует встроенного механизма вне конструкторов и деструкторов.

Ближе всего вы можете получить базовые методы самостоятельно или используя template method pattern.

class B{ 
public: 
    B(); 
    void doSomething(); 
}; 

class A : public B{ 
public: 
    A(); 
    void doSomething() 
    { 
     B::doSomething(); 
    } 
} 
+0

Я думаю, что пример вызова базовой функции значительно улучшил бы этот ответ. – Angew

2

Это не представляется возможным непосредственно, однако вы можете добиться чего-то достаточно близко, используя Non-virtual interface idiom следующим образом:

class A { 
public: 
    void someFunction() { 
     //put the base's code here 
     someFuncImpl();//Calls the private function here 
     //or here, as you see fit 
    }   
private: 
    virtual void someFuncImpl();//potentially pure: = 0; 
}; 

, а затем в другом классе:

class B : public A { 
private: 
    virtual void someFuncImpl() { 
     //Derived's code goes here 
    } 
}; 

Таким образом, когда вы вызываете someFunction() по классу B, вы получите как код производного класса , так и код базового класса выполняется каждый раз.

Это не так просто, как конструкторы могут это сделать, но я думаю, что это самое близкое и простое, что вы получите. Вы получаете в качестве бонуса выбор для запуска кода базы до или после кода производного.

+0

Mmm .. is 'someFunc()' отсутствует в коде B? – ABCplus

+0

Нет, но я забыл объявить 'B' как' public A'. Вам не нужно объявлять 'someFunction()' в 'B', потому что, поскольку он наследует' A', он также имеет функцию-член. – JBL

1

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

Вызов функции базы из функции производного класса будет работать;

void A::doSomething() 
{ 
    B::doSomething(); 
    executeACode(); 
} 

Использование template method pattern (как он используется в ++ IO C потоков библиотеки), также известный как NVI - non virtual interface, также будет работать;

class B { 
    void executeBCode(); 
    virtual void doSomethingImp() = 0; // or not pure 
public: 
    void pubDoSomething() { // public facing 
     executeBCode(); // order these as required 
     doSomethingImp(); 
    } 
}; 

class A { 
    void executeACode(); 
    void doSomethingImp() override // internal implementation 
    { 
     executeACode(); 
    } 
}; 
+0

В последнем примере вызов 'A.doSomething()' приводит к выполнению только 'executeACode();' – ABCplus

+0

. Вызывающим кодом будет 'A.pubDoSomething();' – Niall

Смежные вопросы