Доступ к данным из вложенного класса элегантно - PullRequest
2 голосов
/ 11 октября 2019

У меня есть следующий класс:

class BigNum
{
public:
    BigNum(string StrNumber) : Number(std::move(StrNumber)) {}
    BigNum(const char *StrNumber) : Number(string(StrNumber)) {}
    ~BigNum() = default;

    struct
    {
        string HEX() { return Number + " - HEX"; }
        string DEC() { return Number + " - DEC"; }
        string BIN() { return Number + " - BIN"; }
    }ToString;

private:
    string Number;
};

И, наконец, я получаю элегантный доступ к функциям из этой структуры следующим образом:

BigNum a = "1234";
cout << "a = " << a.ToString.DEC() << endl;
cout << "b = " << a.ToString.HEX() << endl;

Проблема в том, чтоЯ не могу получить доступ к переменной Number из своей структуры.

Я знаю, что что-то подобное решит мою проблему:

struct
{
    string HEX(BigNum &parent) { return parent.Number + " - HEX"; }
...
}ToString;

Проблема с этим решением состоит в том, что не всегда удобнопередать указатель на мой экземпляр.

Каким было бы решением в этом случае иметь данные во вложенном классе и в то же время сохранять вызовы такими простыми, как a.ToString.DEC()?

Ответы [ 2 ]

2 голосов
/ 11 октября 2019

В некотором смысле вы должны дать ToString ссылку или указатель на объект BigNum, чтобы вы могли получить доступ к Number. Примерно так:

class BigNum
{
public:
    BigNum(string StrNumber) : Number(std::move(StrNumber)) {}
    BigNum(const char* StrNumber) : Number(string(StrNumber)) {}
    ~BigNum() = default;

    // you can make the struct private so the type is not visible externally
    struct ToStringType
    {
    private:
        const BigNum& ref;

    public:
        ToStringType(const BigNum& r) : ref(r) {}

        string HEX() { return ref.Number + " - HEX"; }
        string DEC() { return ref.Number + " - DEC"; }
        string BIN() { return ref.Number + " - BIN"; }
    };

    ToStringType ToString{ *this };

private:
    string Number;
};

Не имеет значения, но я бы порекомендовал просто иметь отдельные функции ToStringHex, ToStringDec и ToStringBin. Экономит на том, что не сохраняет ссылки, плюс API проще в этом.

1 голос
/ 11 октября 2019

Я не вижу никакого обоснования в структуре ToString.

Просто оставьте методы в BIGNUM, и все готово.

Однако для этого конкретного приложения (изменение стиля рендеринга вашего данного объекта в ostream) я бы позволил вашему объекту печататься с типичной перегрузкой operator<<, а затем изменил бы стиль рендеринга, используяio-манипуляторы, так что вы сможете:

cout << "a (DEC) = " << BigNum::DEC << a << endl;
cout << "a (HEX) = " << BigNum::HEX << a << endl;

Полноценный пример:

#include <iostream>
#include <iomanip>

using namespace std;

class BigNum
{
public:
    BigNum(string StrNumber) : Number(std::move(StrNumber)) {}
    BigNum(const char *StrNumber) : Number(string(StrNumber)) {}
    ~BigNum() = default;

    static std::ios_base& DEC(std::ios_base& os) {
        os.iword(rendering_style_xalloc) = 0;
        return os;
    }

    static std::ios_base& HEX(std::ios_base& os) {
        os.iword(rendering_style_xalloc) = 1;
        return os;
    }

    static std::ios_base& BIN(std::ios_base& os) {
        os.iword(rendering_style_xalloc) = 2;
        return os;
    }
private:
    static int rendering_style_xalloc;
    string Number;

    friend ostream &operator << (ostream &ostr, const BigNum &bignum);
};

int BigNum::rendering_style_xalloc = std::ios_base::xalloc();

ostream &operator << (ostream &os, const BigNum &bignum) {
    switch (os.iword(BigNum::rendering_style_xalloc)) {
        case 0:
            os << bignum.Number << " - DEC";
            break;
        case 1:
            os << bignum.Number << " - HEX";
            break;
        case 2:
            os << bignum.Number << " - BIN";
            break;
        default:
            os << bignum.Number << " - UNK";
            break;
    }
    return os;
} 

int main(int argc, char **argv)
{
    BigNum a = "1234";
    cout << BigNum::DEC << "a (DEC) = " << a << endl;
    cout << BigNum::HEX << "a (HEX) = " << a << endl;   
}

Ссылки: https://en.cppreference.com/w/cpp/io/ios_base/iword

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...