cpp*_*elp 15 c++ virtual inheritance
class base
{
public:
virtual void start();
virtual void stop();
void doSomething() { start(); .... stop(); }
}
class derived : public base
{
public:
void start();
void stop();
}
Run Code Online (Sandbox Code Playgroud)
但是当我调用doSomething()派生类时,它使用它自己的定义Start()而Stop()不是派生类.
我不想doSomething()在派生类中重写,因为它与基类相同.我究竟做错了什么?
对不起,如果不清楚.
派生类中Start()和Stop()的行为是不同的(它是一个不同的机器) - 但我想使用原始基类doSomething(),因为它没有改变.它只需要使用新的派生类代码start()和stop().
Rob*_*edy 25
您发布的代码应该按照您想要的方式工作.调用doSomething一个实例derived将调用被覆盖的start和被stop定义的函数derived.
但是有一个例外.如果你doSomething在构造函数或析构函数中调用base(无论是直接还是间接),那么被调用的start和stop将被定义的版本base.那是因为在那种情况下,你实际上还没有有效的derived实例.它不是完全构造的或部分破坏的,因此该语言阻止您调用将使用部分对象的方法.
如果你没有从base构造函数或析构函数中调用它,那么问题就比这里显示的更多了.
更新
根据您在下面的评论,您试图让doSomething()调用Derived类的start()和stop()版本,我对您的问题的更新答案如下:
您定义Base和Derived的方式没有任何问题.您可能正在经历所谓的"代码切片",您在声明类型为"Base"的对象上调用"doSomething()",而不是"Base*"或"Base&",这将导致对象成为转换为Base类型.
不好的例子:
Derived derived;
Base base = derived;
base.doSomething(); // This is Base's version of doSomething()
Run Code Online (Sandbox Code Playgroud)
好例子:
Base* base = new Derived; // NOTE: declared type is "Base*"
base->doSomething(); // This will call Derived version
delete base;
Run Code Online (Sandbox Code Playgroud)
注意:你应该使用scoped_ptr,shared_ptr,unique_ptr或其他一些智能指针类,而不是像我的例子那样直接使用指针; 但是,为了不掩盖这个问题,我选择在这个例子中使用原始指针.有关"切片"的更多信息,请参阅:
原始解决方案
您可以执行以下操作:
class Base {
public:
Base() {}
virtual ~Base() {}
virtual void start() {
startInternal();
}
virtual void stop() {
stopInternal();
}
void doSomething() {
startInternal();
// ...
stopInternal();
}
private:
void startInternal() {
// ...
}
void stopInternal() {
// ...
}
};
class Derived : public Base {
public:
Derived() {}
virtual ~Derived() {}
virtual void start() {
// ...
}
virtual void stop() {
// ...
}
};
Run Code Online (Sandbox Code Playgroud)
如果你这样做,那么doSomething()将使用未被覆盖的内部版本的start/stop.当构造函数/析构函数需要与虚方法共享逻辑时,您会发现很多这种模式.
此外,与手头的问题无关,不要忘记每当创建具有虚方法的类时,都应始终创建虚拟析构函数.
| 归档时间: |
|
| 查看次数: |
35125 次 |
| 最近记录: |