C ++: Как предотвратить изменение производного объекта через указатель на его базовый подобъект?

Вы можете использовать классы, найденные в System.Json Namespace , которые были добавлены в .NET 4.5. Вам нужно добавить ссылку на сборку System.Runtime.Serialization

Метод JsonValue.Parse () анализирует текст JSON и возвращает JsonValue :

JsonValue value = JsonValue.Parse(@"{ ""name"":""Prince Charming"", ...");

Если вы передадите строку с объектом JSON, вы сможете записать это значение в JsonObject :

using System.Json;


JsonObject result = value as JsonObject;

Console.WriteLine("Name .... {0}", (string)result["name"]);
Console.WriteLine("Artist .. {0}", (string)result["artist"]);
Console.WriteLine("Genre ... {0}", (string)result["genre"]);
Console.WriteLine("Album ... {0}", (string)result["album"]);

Классы очень похожи на классы, найденные в System.Xml.Linq Namespace .

2
задан Igor G 22 February 2019 в 16:59
поделиться

1 ответ

Отказ от ответственности: Я отвечаю на вопрос в том виде, в котором он был задан, но если вы задаетесь вопросом, как этого добиться, то, скорее всего, что-то не так с вашим дизайном.

Краткий ответ: это нельзя сделать с помощью публичного наследства, полная остановка. Весь смысл общественного наследования заключается в том, что референс или указатель на объект из Derived могут использоваться как ссылка или указатель на объект из Base, независимо от контекста.

Таким образом, способ сделать это - пройти через частное наследование или переменную-член и открыть член Base только через метод доступа, возвращающий ссылку или указатель const:

#include <string>
struct Base
{
    // Mutating method. Not a chance of making it virtual.
    template <typename Anything>
    Base& operator=(const Anything& x)
    {
        m_int = x.AsInteger();
        return *this;
    }

    int AsInteger() const
    {
        return m_int;
    }

    int  m_int;
};

struct Derived : private Base
{
    template <typename Anything>
    Derived& operator=(const Anything& x)
    {
        m_text = x.AsString();
        Base::operator=(x);
        return *this;
    }
    const std::string& AsString() const
    {
        return m_text;
    }

    const Base& base() const {return *this;}

    // Invariant: Derived::m_text matches Base::m_x.
    std::string   m_text;
};

void ExamineBase(const Base* b)
{
    b->AsInteger();
}

void ExamineBase(const Base& b)
{
    b.AsInteger();
}

void InitBase(Base* b)
{
    *b = Base();
}

void InitBase(Base& b)
{
    b = Base();
}


int main()
{
    Base           b;
    InitBase(b);          // <----- (1)
    InitBase(&b);         // <----- (2)

    Derived        d;
    Derived&       ref = d;
    Derived*       ptr = &d;

    ExamineBase(ref.base());     // <----- (3)
    ExamineBase(&ptr->base());     // <----- (4)

    InitBase(ref.base());        // <----- BOOM!
    InitBase(&ptr->base());        // <----- BOOM!

    return 0;
}
0
ответ дан Frank 22 February 2019 в 16:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: