C++ 多态性无法按预期工作



请考虑以下代码:

#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 类的指针。无论如何,我尝试将派生类更改为以下内容:

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需要一个引用来派生,因为在我的实际实现中,即我希望能够做到这一点:

Derived d1;
Derived d2;
d1.foo(d2, 0, 1);

此外,我可能应该更清楚地了解我实际上在问什么。我意识到删除纯虚函数衰减

virtual void foo(Base&, const int&, const int&) const = 0;

修复了此问题。但是,在所有派生类实现中,代码完全相同,只是第一个参数(来自 Base 的派生类)的类型不同。所以感觉应该有一个纯粹的虚函数来强制foo的存在。

问题

在基类中定义纯虚拟成员函数:

virtual void foo(Base&, const int&, const int&) const = 0;

但是您在派生的函数中提供了具有另一个签名的函数:

void foo(Derived&, const int&, const int&) const;

因此,在派生类中还有一个成员函数(重载:名称相同但参数类型不同),但仍然继承纯虚函数。 因此,派生类与基类一样抽象,不允许实例化它。

解决方案

在派生类中更改签名,使其与纯虚拟 bas e 成员函数匹配:

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; 
}

最终,我遇到了这个:C++中的指针变量和引用变量有什么区别?

我的结论是,因为:

  1. 引用不能重新绑定,必须在初始化时绑定,然后行:

    rBase = rDeriv;

仅触发 stBase 复制运算符,它不会重新绑定 rBase。

    引用
  1. 可以看作是类型变量的别名 =>通过引用不可能实现多态性。

相关内容

  • 没有找到相关文章

最新更新