我试图理解带有指针和虚函数的派生类是如何工作的。我想要做的是使用基类中的虚函数,以便它将类类型的指针作为参数。当我从虚函数定义派生类及其函数时,我希望它们将派生类指针作为参数。
我有以下代码
#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 类中的函数将不再起作用。
在您的第一个代码示例中,您继承自纯虚拟类
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
时,不会调用派生类的析构函数。这意味着潜在的内存安全问题。虚拟析构函数意味着派生类的析构函数被正确调用。