创建抽象类 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() 看到的,我不希望这个类能够被实例化。我将为此设置子类:IPv4AddressIPv6AddressTimestamp 等。

我很确定我正在慢慢掌握虚函数并在派生类中重载它们。但是,我仍在努力解决如何最好地处理成员变量(definitionraw_dataformatted_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 的最佳方式是啥?的主要内容,如果未能解决你的问题,请参考以下文章

从 PHP 应用程序中抽象数据库的最佳方法是啥?

java抽象工厂的使用意图是啥?

设计模式之抽象工厂模式

我需要正确理解 Java 中的抽象是啥? [复制]

设计模式--抽象工厂模式

编写数据访问对象 (DAO) 的最佳方法是啥?