【问题标题】:Pure virtual functions with arguments of the same class具有相同类参数的纯虚函数
【发布时间】:2015-12-20 02:02:58
【问题描述】:

如果有人能告诉我这里发生了什么,我将不胜感激:假设我声明以下内容

class Base {
public:
    virtual void member(Base b) = 0;
};

给出以下编译器错误:

pvf.cpp:3:18: error: cannot declare parameter ‘b’ to be of abstract type ‘Base’
     virtual void member(Base b) = 0;
              ^
pvf.cpp:1:7: note:   because the following virtual functions are pure within ‘Base’:
     class Base {
   ^
pvf.cpp:3:18: note:     virtual void Base::member(Base)
     virtual void member(Base b) = 0;

但是,如果我通过引用传递,它编译没有问题:

class Base {
public:
    virtual void member(Base& b) = 0;
};

此外,我想在派生类中实现 member() 为

class Base {
public:
virtual void member(Base& b) = 0;
};

class Derived : public Base {
public:
    void member(Derived& d) {};
};

int main() {
    Derived d;
}

但是,(显然?)我明白了

pvf.cpp: In function ‘int main()’:
pvf.cpp:12:14: error: cannot declare variable ‘d’ to be of abstract type ‘Derived’
    Derived d;
    ^
pvf.cpp:6:8: note:   because the following virtual functions are pure within ‘Derived’:
    class Derived : public Base {
    ^
pvf.cpp:3:15: note:     virtual void Base::member(Base&)
    virtual void member(Base& b) = 0;

【问题讨论】:

  • 如果你声明member(Base b)(不带引用),那就意味着每次有人调用member时,参数都会按值传递并复制(如果传递的对象实际上是@ 987654328@,复制过程中会被切片)。
  • 是的。一切如预期。使用Base&。你有什么问题?

标签: c++


【解决方案1】:

你的第一个函数

virtual void member(Base b) = 0;

通过值获取Base 类的参数,这需要将Base实例 传递给它。但是由于Base 是一个抽象类(因为它包含一个纯虚函数)它不能被实例化,因此你不能创建一个Base 的实例来传递给它!这就是您的第一个错误的原因。

在第二种情况下,在派生类中声明一个函数

void member(Derived& d) {};

你可能认为它覆盖了基类虚函数

virtual void member(Base& b) = 0;

但它没有(事实上,它隐藏了它 - 请参阅 Why does a virtual function get hidden? 以获取对此的解释),因此 Derived 仍然是抽象类,因为您 提供了基类中的纯虚函数。因此,Derived 也无法实例化。无法为基类纯虚函数提供实现的派生类将与基类一样保持抽象。

【讨论】:

  • 谢谢!我想要实现的是一个基类,它强制其所有派生类实现传值方法 Derived::member(Derived d)。我在处理这一切都错了吗?
  • @user:我们必须更多地了解您的特定应用程序以确定这是否“错误”,但使用奇怪的重复模板模式(CRTP)当然是可能的:template<typename TDerived> class Base { public: virtual void member(TDerived b) = 0; }; class Derived : Base<Derived> { ... }; .不过,这可能不是您真正想要的……
  • 我正在编写一些统计软件,我希望能够在通用代码中执行 Distribution::sample(Parameters p) 之类的操作,但我希望能够插入在运行时的分布类型中,例如 Gaussian::sample(NormalParam p) 等,其中 Gaussian 派生自 Distribution 而 NormalParam 派生自 Parameters,我想断言所有分布都实现 ::sample() .观察类要求我将同一类的对象传递给方法。按值传递只是我偶然发现的一种好奇心,而不是要求 - 一直在努力学习 ;-)
  • 使用对基础的引用。
  • 您能否详细说明一下,请(对不起,如果您说的很明显 - 我真的是 C++ 的菜鸟......)
猜你喜欢
  • 1970-01-01
  • 2016-04-19
  • 1970-01-01
  • 1970-01-01
  • 2020-07-18
  • 2016-01-01
  • 2016-07-22
  • 2011-11-29
  • 2018-08-05
相关资源
最近更新 更多