我有以下抽象类:
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)