我有一个抽象基类,看起来像这样:
class AbstractClass {
public:
virtual ~AbstractClass() = 0 {}
std::string GetName() const { return m_Name; }
private:
std::string m_Name;
};
现在我有很多派生类,我想像这样实现它们
class DerivedClass1 : public AbstractClass{
public:
DerivedClass1() = default;
~DerivedClass1() = default;
private:
std::string m_Name = "DerivedClass1";
};
int main() {
DerivedClass1 class1;
std::cout << class1.GetName();
return 0;
}
每次我派生一个Class时,我都不想重写GetName(),这可能吗?编辑:我收到链接器错误。错误LNK2019。
在基类中只使用一个名称,在参数中使用带有参数的构造函数:
class AbstractClass{
public:
AbstractClass(const std::string& name) : m_Name(name){}
std::string GetName() const { return m_Name; }
private:
std::string m_Name;
};
DerivedClass1 : public AbstractClass{
public:
DerivedClass() : AbstractClass("DerivedClass1") {}
};
int main(){
DerivedClass1 class1;
std::cout << class1.GetName();
return 0;
}
似乎没有理由使基类抽象,但如果你确实需要它,即使纯虚拟析构函数必须有一个定义,否则你会得到一个链接器错误,因为它在销毁派生对象时是必需的。
此外,如果析构函数不存在,m_Name
什么时候会被销毁?
class Abstract
{
public:
virtual ~Abstract() = 0;
};
Abstract::~Abstract() {}
这使得一个类无法实例化,但其派生类仍然可以被销毁。
这不是你“覆盖”GetName()
的方式。您可以将GetName()
设为虚拟并在派生类中覆盖它:
class AbstractClass {
public:
virtual ~AbstractClass() = default;
virtual std::string GetName() const { return "AbstractClass"; }
private:
std::string m_Name;
};
和:
class DerivedClass1 : public AbstractClass {
public:
DerivedClass() = default;
std::string GetName() const override { return "DerivedClass1"; }
};
或者,您可以通过将m_Name
传递给基类构造函数来在其中设置class AbstractClass {
public:
AbstractClass(const std::string& name) : m_Name(name) {}
virtual ~AbstractClass() = default;
std::string GetName() const { return m_Name; }
protected: // protected not private
std::string m_Name;
};
:
class DerivedClass1 : public AbstractClass {
public:
DerivedClass() : AbstractClass("DerivedClass1") {}
};
和:
class AbstractClass {
public:
virtual ~AbstractClass() = default;
std::string GetName() const { return m_Name; }
protected: // protected not private
std::string m_Name;
};
或者您可以在派生类的构造函数中设置它:
class DerivedClass1 : public AbstractClass {
public:
DerivedClass() : AbstractClass() { m_Name = "DerivedClass1"; }
};
和:
AbstractClass
您收到链接错误,因为AbstractClass::~AbstractClass()
{
// Compulsory virtual destructor definition,
// even if it's empty
}
的析构函数需要定义,即使它是空的。
LIVE on Wandbox
getName
关于压倒class ClassName {
public:
virtual ~ClassName() {} // just to enable RTTI for all decendants
std::string getClassName() {
return typeid(*this).name();
}
};
:你不必。如果未在派生类中提供实现,则使用继承的实现。
代码提示问题是如何获得类名?但这没有明确说明(XY问题)
如何处理类名?
你可以使用RTTI:
https://wandbox.org/permlink/LvPdA37arMr0LFQW
https://wandbox.org/permlink/8XiB7yVOM0wYVxpl
但是你可以看到它增加了一些额外的前缀(它是编译器所依赖的)。 boost可以清理它:
qazxswpoi