我一直在我正在创建的库中使用一种模式,该模式使用将对象的字符串名称传递给其基础对象的构造函数。我试过使用 std::string 和 c 风格的字符串,但在使用 Valgrind 时总是出现奇怪的内存错误。
class Base {
public:
Base( std::string name ) : name(name) {}
virtual ~Base() {}
std::string getName() { return name; }
private:
std::string name;
};
class Derived : public Base {
public:
Derived() : Base("Derived") {}
};
int main() {
Base* derived = new Derived;
std::cout << derived->getName() << "\n";
delete derived;
}
(这在 Valgrind 中编译和运行良好)
这样的东西安全吗?我现在使用的是“const char*”而不是“std::string”,这样安全吗?
是否有更安全的替代方案,最好不使用虚拟机?
编辑:有没有办法用模板做到这一点?我不想使用 RTTI,因为它的名称被破坏了,我希望名称是“正常的”以便与脚本/数据持久性一起使用。
最佳答案
你在这里做的一切都很好。
模板不会给你带来任何好处,因为你仍然需要在基类中存储一个运行时指针以进行动态识别。
智能指针不会给你带来任何好处,因为字符串的生命周期就是整个程序。如果您不计算任何内容,char const *
和从字符串文字进行初始化是理想的选择。如果要计算字符串,则可以使用包含在 getter 函数中的 static std::string const
。
class Derived : public Base {
public:
Derived() : Base(get_name()) {}
private:
static std::string const & get_name() {
static std::string const name = "Derived"; // or = compute_name();
return name;
}
};
这避免了静态初始化顺序的失败。 (getter 函数从编译器接收额外的多线程安全防护。)string
的生命周期就是程序的生命周期。 Base
可能存储一个string const &
或一个char const *
,这并不重要。我会推荐 char const *
,因为 string
引用可能会被临时初始化。
关于c++ - 编译时字符串赋值用于运行时识别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17777850/