创建抽象类 DataType 的最佳方式是啥?
Posted
技术标签:
【中文标题】创建抽象类 DataType 的最佳方式是啥?【英文标题】:What is the best way for me to create my abstract class DataType?创建抽象类 DataType 的最佳方式是什么? 【发布时间】:2018-12-30 19:16:31 【问题描述】:自从我使用类 C 语言(包括 C++)以来,已经很长时间了。我目前的工作主要集中在 Python 上,而 C++ 处理继承的方式让我有些沮丧。我需要能够读取日志文件并根据预定义的模式提取重要信息,以便在所述日志中查找。
我有一个抽象类DataType
:
#include <string>
using namespace std;
class DataType
public:
// Getters
virtual string GetRawData() const;
virtual string GetFormattedData() const;
protected:
// Transform raw data (if possible)
virtual int Transform(string raw, string &fmt) = 0;
// A pattern string (regex) to compare against raw_data to see
// if can be transformed into a normalized format
static string definition;
string raw_data;
string formatted_data;
;
正如你通过纯虚函数Transform()
看到的,我不希望这个类能够被实例化。我将为此设置子类:IPv4Address
、IPv6Address
、Timestamp
等。
我很确定我正在慢慢掌握虚函数并在派生类中重载它们。但是,我仍在努力解决如何最好地处理成员变量(definition
、raw_data
和 formatted_data
)。特别是definition
,我真的希望所有派生类都有自己的值,但是对于每个类,该变量应该是静态的。我的问题是在哪里声明,在哪里定义?
当我在 IPv4Address.h 中定义 definition
时,就像我的派生类 IPv4Address
现在一样:
class IPv4Address : public DataType
//stuff above
protected:
// I know the pattern doesn't work matching IP addresses.
// I'm just trying to get this to compile without error for now.
static string definition = "[a-zA-Z_][a-zA-Z_0-9]*\\.[a-zA-Z0-9]+";
//stuff below
我收到此错误:
in-call initialization of static data member 'std::__cxx11::string IPv4Address::definition of non-literal type
我需要在 cpp 文件中定义这个变量吗?这对我来说似乎不对,但这并不意味着什么。感谢您的帮助!
【问题讨论】:
不能在类定义中初始化静态变量。它需要在类定义之外。此外,不幸的是,没有办法强制每个派生类都有一个特定的静态变量(如纯虚拟静态变量),所以我会将它排除在基类之外。编辑:除非您使用 C++17(需要指定),否则您可以在其中使用inline
变量。见en.cppreference.com/w/cpp/language/static。作为记录,如果您是 C++ 新手,cppreference 是一个很好的资源。 将来自 python 令人沮丧。
顺便说一句,关于超出问题范围的事情,我相信the metaclasses proposal 会启用这样的功能。
加const
怎么样?
请说明您打算如何使用这个definition
变量。您可能尝试使用错误的语言功能来解决您的问题。
@r3musn0x definition
变量用作 DataType 派生类的“定义”。因此,对于 IPv4Address,definition
将是一个正则表达式样式的字符串,可以将原始数据输入与之进行比较,以验证该原始数据是否是 IPv4 地址。
【参考方案1】:
通常在 C++ 中,静态数据成员必须在类外部(通常在 .cpp 文件中)定义,如下所示:
string IPv4Address::definition = "[a-zA-Z_][a-zA-Z_0-9]*\\.[a-zA-Z0-9]+";
但是,在您的情况下,根本不需要此数据成员,尤其是在您的基类 DataType
中。数据成员不能在派生类中被覆盖,因此当您在 DataType
类中声明 definition
成员并在 IPv4Address
类中“重新定义”它时,您实际上定义了两个独立的不相关变量,这对您没有任何帮助基于类类型的不同模式。例如:
void foo(DataType &data)
cout << data.definition; // assuming "definition" is public for the sake of example
void bar()
IPv4Address addr;
foo(addr); // will output the DataType::definition and not IPv4Address::definition because the "definition" data member is not "virtual" and there is really no such thing
鉴于您的 Transform
方法将是使用此 definition
的方法,并且在每个类中都会有所不同,您可以完全摆脱此数据成员,并将其作为 Transforms
的一部分定义。
【讨论】:
以上是关于创建抽象类 DataType 的最佳方式是啥?的主要内容,如果未能解决你的问题,请参考以下文章