C ++ два производных класса содержат объекты друг друга (включают проблему) - PullRequest
0 голосов
/ 25 апреля 2018

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

  • json.hpp
    • jsonobject.hpp
    • jsonarray.hpp

В каждом из файлов есть определение класса (JSON, JSONObject: public JSON, JSONArray: public JSON), а последние два оба имеют функции, у которых другой является параметром (а не как ссылочный тип, поэтому простое предварительное объявление не решает проблему). Эти файлы:

json.hpp:

#ifndef _JSON
#define _JSON

#include <string>
#include <iostream>
#include "../../lib/simplejson/json.hpp"

class JSON{
    protected:
        std::string content;
    public:
        JSON(std::string content) : content(content)
        {}

        operator std::string()
        {return content;}

        friend std::ostream& operator<<(std::ostream&, JSON&); 

};

inline std::ostream& operator<<(std::ostream& os, JSON& content)
{
    os<<content.content;
    return os;
}
#endif

jsonobject.hpp:

#ifndef _JSONOBJECT
#define _JSONOBJECT

#include "json.hpp"
class JSONArray;

class JSONObject : public JSON {
    public:
        JSONObject(std::string= "{}");

        JSONObject get(std::string);

        template<typename T> void put(std::string, T);

        operator int();

        JSONObject operator[](int);

};

inline JSONObject::operator int() {return atoi(content.c_str());}


inline JSONObject::JSONObject(std::string content) : JSON(content) {}

inline JSONObject JSONObject::get(std::string key) {
    json::JSON obj = json::JSON::Load(content);
    JSONObject json(obj[key].dump());
    return json; }

template<typename T> inline void JSONObject::put(std::string key, T value) {
    json::JSON obj = json::JSON::Load(content);
    obj[key] = value;
    content = obj.dump(); } template<> inline void JSONObject::put<JSON&>(std::string key, JSON& value) {
    json::JSON obj = json::JSON::Load(content);
    json::JSON obj2 = json::JSON::Load((std::string)value);
    std::cout<<obj2<<std::endl<<std::endl;
    obj[key] = obj2;
    content = obj.dump();     } template<> inline void JSONObject::put<JSONObject>(std::string key, JSONObject value) {  //here is JSONObject used in a manner which requires it not to only be forward-declared
    (*this).put(key, dynamic_cast<JSON&>(value)); } template<> inline void JSONObject::put<JSONArray&>(std::string key, JSONArray& value) {
    (*this).put(key, dynamic_cast<JSON&>(value)); }
#endif

jsonarray.hpp:

#ifndef _JSONARRAY
#define _JSONARRAY

#include "jsonobject.hpp"

class JSONArray : public JSON{
    public:
        JSONArray(std::string = "[]");

        JSON operator[](int n);

        template<typename T> void add(int, T);

};

inline JSONArray::JSONArray(std:: string content) : JSON(content)
{}

inline JSON JSONArray::operator[](int n)
{
    json::JSON obj = json::JSON::Load(content);
    JSONObject json(obj[n].dump());    //Here is JSONObject instantiated, which does not work with only forward-declarataion
    return json;
}

template<typename T> inline void JSONArray::add(int n, T t)
{
        json::JSON obj = json::JSON::Load(content);
        obj[n] = t;
        content = obj.dump();
}
template<> inline void JSONArray::add<JSON>(int n, JSON t)
{
        json::JSON obj = json::JSON::Load(content);
        json::JSON obj2 = json::JSON::Load((std::string)t);
        obj[n] = obj2;
        content = obj.dump();
}
#endif

Чего мне не хватает? Я тоже пытался поместить их все в один файл, это тоже не помогло.

1 Ответ

0 голосов
/ 25 апреля 2018

Нет, это тебе не поможет. Вам нужно переместить реализацию в отдельный класс, чтобы разорвать цикл и использовать прямую ссылку реализации в одном из классов. Техника называется Чеширским котом и выглядит примерно так:

A.hpp
// AImple uses B.
class AImpl;

class A
{
    AImpl* impl;
public:
    void f(); // f uses impl.
};

B.hpp

#include "a.hpp"

class B
{
    A a; // B can use A here.
};

A.cpp
#include "a.hpp"
#include "aimpl.hpp"

void A::f()
{
   impl -> f();
}

AImpl.cpp
#include "b.hpp"
#include "AImpl.hpp"

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