gpt4 book ai didi

c++ - 静态成员的继承与保护

转载 作者:太空宇宙 更新时间:2023-11-04 16:25:13 25 4
gpt4 key购买 nike

我确实有一个关于静态成员继承及其在 C++ 中的保护的问题。我希望我会足够清楚,因为写思维状态并不总是那么容易:)我正在为一个图形程序编写一个简单的(文本解析器),它正在加载具有自定义格式的文本文件,现在文本部分几乎完成了并且现在我需要生成一些对象来为它们提供我从文件加载的数据。

我认为这个问题属于 C++ 的第 1 小时,但我卡住了。例如,我从文本文件中仅加载了两种类型的逻辑“节点”,LAYER 和 PLINE,它们也具有可以或不可以为两者共有的属性。 LAYER 与 PLINE 的关系现在完全不相关,困扰我的是如何连接和处理两者的属性:

假设我选择DataObj 作为两者的基类。 DataObj 有一个名为“name”的成员,因为 LAYER 和 PLINE 都可以有一个名字。 LAYER 有一个只对图层通用的属性,例如。 “锁定”,并且 PLINE 具有仅对 pline 例如常见的属性。 “颜色”。在做事的“学校方式”中,它看起来像:

/// i use const char* for everything to not complicate things ... 
...
class DataObj {
...
const char* name;
...
}
...
class Layer : public DataObj {
...
const char* locked;
...
}
...
class Pline : public DataObj {
...
const char* color;
...
}
...
int main(){
Layer* l = new Layer();
l.name = "first layer";
l.locked = "false";

Pline* p = new Pline();
p.name = "wonderful line";
p.color = "0xFF3300";
}
...

现在我想更“动态地”做这件事,因为我真的不关心静态类型的成员名称(将来可能还有访问器),尤其是在为对象提供来自解析器的数据时。我的意思是只使用 2 种节点类型很容易做到这一点,但我会有超过几十种。

所以我想做的概念是“静态地”推送每个节点类型(类)允许属性的 vector ,然后只检查对象中是否允许该属性并在解析期间设置它。我可能想要 2 个重要成员 1. 是 kv 对的 std::map,第二个是特定节点允许属性的静态 vector 。按照之前输入的代码:

...
class DataObj {
...
static std::vector<const char*> allowedAttrs;
std::map <const char*, const char*> attrs;

private:
static bool isInit;
...
}
...
DataObj::DataObj(){
if(!isInit)
allowedAttrs.push_back("name");
isInit = true;
}
...
Layer::Layer(){
if(!isInit) // private static for Layer
allowedAttrs.push_back("locked");
}
...
Pline::Pline(){
if(!isInit) // private static for Pline
allowedAttrs.push_back("color");
}
...

我在这里遇到的问题可能从月球上就可以看到。如果我们先初始化一个新层,然后初始化一个新的 Pline,Pline 将在 allowedAttrs vector 中有名称、锁定和颜色,这是不正确的,因为“锁定”应该只对层节点有效。

所以我需要一些方法来解决这个问题,方法是成员“allowedAttrs”对于层对象中的“锁定”等不常见属性变为“私有(private)”,但同时保留其父类(super class)的“公共(public)”性质“DataObj"- 因此它可以捕获共享属性,如"名称"。换句话说,我不想“破坏”上升到基类的“继承流”,并为每个节点类(对象)定义新变量,一遍又一遍地重复相同的代码。 (类似于虚拟变量)。

我希望这个问题不是(那么)愚蠢,非常感谢您的回答。

最佳答案

1) 我会为每种类型使用单独的静态成员来保存每种类型允许的属性。
2) 将静态成员移动到函数中,这样更安全,并且可能避免检查它是否一直被初始化(取决于你的编译器有多好和其他细节)
3) 除了非常特殊的事情,不要使用const char*。如果您不知道这些是什么,请始终使用 std::string。在这种情况下,我们必须使用std::string
4) 我将 allowedAttrs 从 vector 更改为 set,这对于大量属性来说可能更快,而对于较小的数字可能更慢。

这是基础:

class DataObj {
const std::set<std::string>& get_allowed_data_attributes() static {
static std::set<std::string> allowedAttrs = {"name"};
return allowedAttrs;
}
std::map <std::string, std::string> attrs;
public:
DataObj(){ }
void set_attribute(std::string key, std::string value) {
auto it = get_allowed_data_attributes().find(key);
if (it == get_allowed_data_attributes().end())
throw bad_key_exception(key);
attrs.insert(std::make_pair(std::move(key), std::move(value)));
}
const std::string& get_attribute(const std::string& key) const {
auto it = attrs().find(key);
if (it == attrs().end())
throw bad_key_exception(key);
return it->second;
}
};

这是派生的:

class Layer : public DataObj {
const std::set<std::string>& get_allowed_data_attributes() static {
static std::set<std::string> allowedAttrs = {"locked"};
return allowedAttrs;
}
public:
DataObj(){ }
void set_attribute(std::string key, std::string value) {
auto it = get_allowed_data_attributes().find(key);
if (it == get_allowed_data_attributes().end())
DataObj::set_attribute(std::move(key), std::move(value));
else
attrs.insert(std::make_pair(std::move(key), std::move(value)));
}
const std::string& get_attribute(const std::string& key) const {
auto it = attrs().find(key);
if (it == attrs().end())
return DataObj::get_attribute(key);
else
return it->second;
}
};

请注意,如果你给它一个无效的 key ,它会抛出一个 bad_key_exception,你必须添加它。确保它继承自 std::runtime_error

关于c++ - 静态成员的继承与保护,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12681332/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com