请考虑以下代码:
#include <iostream>
class Base{
public:
int iB;
Base() :iB(0){};
virtual ~Base(){}
virtual void foo(Base&, const int&, const int&) const = 0;
};
class Derived : public Base{
public:
int iD;
Derived() :iD(1){};
void foo(Derived&, const int&, const int&) const;
};
void Derived::foo(Derived& d, const int& i1, const int& i2) const{
std::cout << d.iD;
}
class BaseWrap{
public:
BaseWrap(){};
virtual ~BaseWrap(){};
virtual Base* bar() const = 0;
protected:
Base* b;
};
class DerivedWrap : public BaseWrap{
public:
DerivedWrap(){};
Derived* bar() const;
private:
Derived* d;
};
Derived* DerivedWrap::bar() const {
return new Derived;
}
int main(){
return 0;
}
这会导致编译器错误“错误:抽象类类型的对象”不允许派生“纯虚函数Base :: foo”没有覆盖。 我假设由于多态性,我总是可以将指针放到一个派生类中,其中指向Base类的指针。无论如何,我尝试将Derived类更改为以下内容:
class Derived : public Base{
public:
int iD;
Derived() :iD(1){};
void foo(Base&, const int&, const int&) const;
};
void Derived::foo(Base& d, const int& i1, const int& i2) const{
std::cout << d.iD;
}
但是,现在我收到错误“错误:类”基数“没有成员”iD“。
编辑:
foo接受ref派生,因为在我的实际实现中,即我希望能够这样做:
Derived d1;
Derived d2;
d1.foo(d2, 0, 1);
此外,我可能应该更清楚我实际要问的是什么。我意识到删除纯虚函数声明
virtual void foo(Base&, const int&, const int&) const = 0;
解决了这个问题。但是,在所有派生类实现中,代码完全相同,并且仅在第一个参数的类型(Base的派生类)中有所不同。所以感觉应该有一个纯虚函数来强制存在foo。
答案 0 :(得分:1)
在基类中定义纯虚拟成员函数:
virtual void foo(Base&, const int&, const int&) const = 0;
但您在派生的函数中提供了另一个签名:
void foo(Derived&, const int&, const int&) const;
因此,在派生类中还有一个成员函数(重载:同名但参数类型不同),但仍继承纯虚函数。因此派生类与基类一样抽象,并且不允许实例化它。
在派生类中更改签名,使其与纯虚拟基本成员函数匹配:
void foo(Base&, const int&, const int&) const;
顺便说一句,无论何时使用虚函数,都要使用override
关键字在编译时发现这些细微的错误,即使对于普通的虚函数也是如此:
void foo(Base&, const int&, const int&) const override;
实际上,一旦使用Base参数定义foo()
,就无法轻松使用iD
成员。
第一种解决方案是使用dynamic_cast告诉您的代码基本实际上是派生对象。当然,你必须检查这个假设是否正确:
void Derived::foo(Base& d, const int& i1, const int& i2) const{
Derived *dp = dynamic_cast<Derived*>(&d);
if (dp) {
std::cout << dp->iD;
}
}
然而,我不清楚为什么你首先需要这个。为什么不摆脱这个第一类型依赖参数并使用当前对象的成员变量:
void Derived::foo(const int& i1, const int& i2) const{
std::cout << iD;
}