派生类使用的抽象类方法

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

我有一个抽象基类,看起来像这样:

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。

c++
4个回答
2
投票

在基类中只使用一个名称,在参数中使用带有参数的构造函数:

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() {}

这使得一个类无法实例化,但其派生类仍然可以被销毁。


1
投票

这不是你“覆盖”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

0
投票

您收到链接错误,因为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(); } }; :你不必。如果未在派生类中提供实现,则使用继承的实现。


0
投票

代码提示问题是如何获得类名?但这没有明确说明(XY问题)

如何处理类名?

你可以使用RTTI:

https://wandbox.org/permlink/LvPdA37arMr0LFQW

https://wandbox.org/permlink/8XiB7yVOM0wYVxpl

但是你可以看到它增加了一些额外的前缀(它是编译器所依赖的)。 boost可以清理它:

qazxswpoi

© www.soinside.com 2019 - 2024. All rights reserved.