C++,使用派生类虚函数并以派生类类型指针作为参数

问题描述 投票:0回答:1

我试图理解带有指针和虚函数的派生类是如何工作的。我想要做的是使用基类中的虚函数,以便它将类类型的指针作为参数。当我从虚函数定义派生类及其函数时,我希望它们将派生类指针作为参数。

我有以下代码

#include <vector>

using std::vector;

class Base
{
 public:
  int value;
  virtual void F(Base *arg)=0;
};

class Derived: public Base
{
  void F(Derived *arg)
{
  // Do something.
}
};

class Derived2: public Base
{
 public:
  vector<int> v;

  void Something()
  {
    // Do something to vector.
  }

  void F(Derived2 *arg)
  {
    // Do something.
  }
};


void solution1()
{
  Base *v1=new Derived;
  Base *v2=new Derived2;
  v2->Something();
}

int main(){
  solution1();
  return 0;
}

运行此命令会出现以下错误

main.cpp: In function 'void solution1()':
main.cpp:5:16: error: invalid new-expression of abstract class type 'Derived'
    5 |   Base *v1=new Derived;
      |                ^~~~~~~
In file included from main.cpp:1:
class.h:12:7: note:   because the following virtual functions are pure within 'Derived':
   12 | class Derived: public Base
      |       ^~~~~~~
class.h:9:16: note:     'virtual void Base::F(Base*)'
    9 |   virtual void F(Base *arg)=0;
      |                ^
main.cpp:6:16: error: invalid new-expression of abstract class type 'Derived2'
    6 |   Base *v2=new Derived2;
      |                ^~~~~~~~
class.h:20:7: note:   because the following virtual functions are pure within 'Derived2':
   20 | class Derived2: public Base
      |       ^~~~~~~~
class.h:9:16: note:     'virtual void Base::F(Base*)'
    9 |   virtual void F(Base *arg)=0;
      |                ^
main.cpp:7:7: error: 'class Base' has no member named 'Something'
    7 |   v2->Something();
      |       ^~~~~~~~~

更改代码:

class Derived: public Base
{
  void F(Base *arg)
{
  // Do something.
}
};

class Derived2: public Base
{
 public:
  vector<int> v;

  void Something()
  {
    // Do something to vector.
  }

  void F(Base *arg)
  {
    // Do something.
  }
};

给我一个新错误

main.cpp: In function 'void solution1()':
main.cpp:7:7: error: 'class Base' has no member named 'Something'
    7 |   v2->Something();
      |       ^~~~~~~~~

我应该如何修复代码?

我希望虚函数能够使用派生类类型作为输入。相反,我收到一个错误,指出虚拟函数是纯函数。如果我通过将参数类型更改为基类类型来解决此问题,Derived2 类中的函数将不再起作用。

c++ pointers virtual-functions derived-class
1个回答
0
投票

在您的第一个代码示例中,您继承自纯虚拟类

Base
,但您没有重写该函数,因为不同的函数采用不同的参数(
Base::F
采用
Base*
,而
Derived::F
采用
Derived*
) ),导致它们具有不同的函数签名。您收到的错误是由于没有覆盖纯虚函数
Base::F
,您已添加后缀
=0
,这意味着它必须被继承它的任何函数覆盖。

在第二个示例中,您更改了代码,以便它正确地继承自

Base*
,从而修复了原始错误。然而,现在你又陷入了另一个错误。第二个错误的原因是您已将派生类 (
Derived2*
) 的指针隐式转换为基类指针 (
Base*
)。这意味着您只能访问
Base*
中的方法,这意味着无法运行
Derived2::Something
等方法。虽然没有完美的方法来实现您的建议,但您可以将
Something
方法添加到
Base
并让
Derived2
覆盖它。

// class.h
#include <stdexcept>

// ...

class Base
{
 public:
  int value;
  virtual void F(Base *arg)=0;
  virtual void Something() // No =0 suffix because we don't want to force overriding it.
  {
    throw std::runtime_error("Not implemented.");
  }
  virtual ~Base() = default; // Virtual destructor.
};

// ...

class Derived2: public Base
{
 public:
  vector<int> v;

  void Something()
  {
    // Do something to vector.
  }

  void F(Base *arg)
  {
    // Do something.
  }
};

// main.cpp
#include <memory>

void solution1()
{
  std::unique_ptr<Base> v1{std::make_unique<Derived>()};
  std::unique_ptr<Base> v2{std::make_unique<Derived2>()};
  v2->Something();
}

int main(){
  solution1();
}

我所做的一些其他更改:

  • 使用唯一指针而不是
    new
    - 之前您使用的是
    new
    而不是调用
    delete
    ,这意味着您正在泄漏内存。有了
    std::unique_ptr
    delete
    就会帮你调用,意味着你不会泄漏任何内存,也不用担心调用delete。
  • 添加了虚拟析构函数 - 当您在派生类的基类指针上调用
    delete
    时,不会调用派生类的析构函数。这意味着潜在的内存安全问题。虚拟析构函数意味着派生类的析构函数被正确调用。
© www.soinside.com 2019 - 2024. All rights reserved.