Каков наилучший способ создания абстрактного класса DataType? - PullRequest
0 голосов
/ 30 декабря 2018

Прошло долго времени с тех пор, как я использовал 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, когда я определяю definitionв IPv4Address.h следующим образом:

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?Мне это не кажется правильным, но это мало что значит.Спасибо за любую помощь!

1 Ответ

0 голосов
/ 30 декабря 2018

Обычно в C ++ члены статических данных должны быть определены вне класса (обычно в файле .cpp) следующим образом:

string IPv4Address::definition = "[a-zA-Z_][a-zA-Z_0-9]*\\.[a-zA-Z0-9]+";

В вашем случае, однако, нет особой необходимости в этом члене данных ввсе, особенно в вашем базовом классе DataType.Члены данных не могут быть переопределены в производном классе, поэтому, когда вы объявляете definition член в DataType классе и «переопределяете» его в 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.

...