如何实现一个abstact类C++

Rom*_*tec 0 c++ inheritance

我有以下抽象类:

class  Weapon
{
  public:
    Weapon(std::string const &name) : _name(name) {}
    virtual void attack() const = 0;
    std::string const &getName() const;
  private:
    std::string const &_name;
};
Run Code Online (Sandbox Code Playgroud)

一个简单的实现

class Shadowmourn : public Weapon 
{
  public:
    ShadowMourn() : Weapon(std::string("Shadowmourn")) {}

    void attack() const override {}
}
Run Code Online (Sandbox Code Playgroud)

我可以编译它,但是当我尝试打印我的devired类的名字时,我得到了一些奇怪的字符.

Weapon *w = new Shadowmourn();
std::cout << "got " << w->getName() << std::endl;
std::cout << "got " << w->getName().c_str() << std::endl;
Run Code Online (Sandbox Code Playgroud)

两个输出都不是预期的..我有一些不可读的字符..那么我的Weapon类的实现是不是很糟糕?

Chr*_*ckl 10

您调用未定义的行为,因为您存储对一个std::string被销毁的引用,即使包含的Weapon存在,然后您尝试访问已经销毁的std::string.

奇怪的输出是在这种情况下可能发生的许多不可预测的事情之一.

解决方案是让你的代码更简单:不要存储std::string const&但是a std::string const.

class  Weapon
{
  public:
    Weapon(std::string const &name) : _name(name) {}
    virtual void attack() const = 0;
    std::string const &getName() const;
  private:
    std::string const _name;
};
Run Code Online (Sandbox Code Playgroud)

您还需要一个虚拟析构函数,您可能希望摆脱数据成员的下划线约定.而且您可能只想getName按值返回以避免悬空引用的进一步麻烦.虽然我们在这里,但具有虚函数的类总是适合删除的复制构造函数和复制赋值运算符.

class  Weapon
{
  public:
    Weapon(std::string const &name) : name(name) {}
    virtual ~Weapon() = default;
    Weapon(Weapon const&) = delete;
    Weapon& operator=(Weapon const&) = delete;
    virtual void attack() const = 0;
    std::string getName() const;
  private:
    std::string const name;
};
Run Code Online (Sandbox Code Playgroud)

  • @Bathsheba:好主意.旧习难改 :) (2认同)