C++ 两个派生 类 中有彼此的对象(包括问题)
C++ two derived classes have objects of each other in them (include issue)
我有以下文件
- json.hpp
- jsonobject.hpp
- jsonarray.hpp
在每个文件中都有一个 class 定义 (JSON, JSONObject : public JSON, JSONArray : public JSON), 后两个 both 都有将另一个作为参数的函数(而不是作为引用类型,所以简单的前向声明确实不能解决问题)。
这些文件是:
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
我错过了什么?我也试过把它们都放在一个文件里,也没用。
不,它不会帮助你。您需要将实现移到单独的 class 中以打破循环并在其中一个 class 中使用实现的前向引用。该技术称为柴郡猫,它是这样的:
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.
我有以下文件
- json.hpp
- jsonobject.hpp
- jsonarray.hpp
在每个文件中都有一个 class 定义 (JSON, JSONObject : public JSON, JSONArray : public JSON), 后两个 both 都有将另一个作为参数的函数(而不是作为引用类型,所以简单的前向声明确实不能解决问题)。 这些文件是:
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
我错过了什么?我也试过把它们都放在一个文件里,也没用。
不,它不会帮助你。您需要将实现移到单独的 class 中以打破循环并在其中一个 class 中使用实现的前向引用。该技术称为柴郡猫,它是这样的:
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.