c++中的动态对象
Dynamic Object in C++?
我意识到我很可能会得到很多"你不应该这样做,因为……"的答案,他们是最受欢迎的,我可能会完全同意你的推理,但我很好奇这是否可能(正如我想象的那样)。
是否有可能在c++中定义一种动态/通用对象类型,在那里我可以动态地创建存储和检索键/值类型系统的属性?例子:
MyType myObject;
std::string myStr("string1");
myObject.somethingIJustMadeUp = myStr;
注意,显然,somethingIJustMadeUp
实际上不是MyType
的已定义成员,但它将被动态定义。然后我可以这样写:
if(myObject.somethingIJustMadeUp != NULL);
或
if(myObject["somethingIJustMadeUp"]);
相信我,我意识到这有多可怕,但我仍然很好奇,是否有可能,是否可以用一种最小化它的可怕的方式。
c++脚本就是你想要的!
的例子:
#include <cppscript>
var script_main(var args)
{
var x = object();
x["abc"] = 10;
writeln(x["abc"]);
return 0;
}
是一个有效的c++
您可以使用std::map
:
std::map<std::string, std::string> myObject;
myObject["somethingIJustMadeUp"] = myStr;
现在,如果您想要泛型值类型,那么您可以使用boost::any
作为:
std::map<std::string, boost::any> myObject;
myObject["somethingIJustMadeUp"] = myStr;
你也可以检查一个值是否存在:
if(myObject.find ("somethingIJustMadeUp") != myObject.end())
std::cout << "Exists" << std::endl;
如果你使用boost::any
,那么你可以知道实际的值的类型,通过调用.type()
:
if (myObject.find("Xyz") != myObject.end())
{
if(myObject["Xyz"].type() == typeid(std::string))
{
std::string value = boost::any_cast<std::string>(myObject["Xyz"]);
std::cout <<"Stored value is string = " << value << std::endl;
}
}
这还展示了如何使用boost::any_cast
来获取存储在boost::any
类型对象中的值。
这可以是一个解决方案,使用RTTI多态性
#include <map>
#include <memory>
#include <iostream>
#include <stdexcept>
namespace dynamic
{
template<class T, class E>
T& enforce(T& z, const E& e)
{ if(!z) throw e; return z; }
template<class T, class E>
const T& enforce(const T& z, const E& e)
{ if(!z) throw e; return z; }
template<class Derived>
class interface;
class aggregate;
//polymorphic uncopyable unmovable
class property
{
public:
property() :pagg() {}
property(const property&) =delete;
property& operator=(const property&) =delete;
virtual ~property() {} //just make it polymorphic
template<class Interface>
operator Interface*() const
{
if(!pagg) return 0;
return *pagg; //let the aggregate do the magic!
}
aggregate* get_aggregate() const { return pagg; }
private:
template<class Derived>
friend class interface;
friend class aggregate;
static unsigned gen_id()
{
static unsigned x=0;
return enforce(++x,std::overflow_error("too many ids"));
}
template<class T>
static unsigned id_of()
{ static unsigned z = gen_id(); return z; }
aggregate* pagg;
};
template<class Derived>
class interface: public property
{
public:
interface() {}
virtual ~interface() {}
unsigned id() const { return property::id_of<Derived>(); }
};
//sealed movable
class aggregate
{
public:
aggregate() {}
aggregate(const aggregate&) = delete;
aggregate& operator=(const aggregate&) = delete;
aggregate(aggregate&& s) :m(std::move(s.m)) {}
aggregate& operator=(aggregate&& s)
{ if(this!=&s) { m.clear(); std::swap(m, s.m); } return *this; }
template<class Interface>
aggregate& add_interface(interface<Interface>* pi)
{
m[pi->id()] = std::unique_ptr<property>(pi);
static_cast<property*>(pi)->pagg = this;
return *this;
}
template<class Inteface>
aggregate& remove_interface()
{ m.erase[property::id_of<Inteface>()]; return *this; }
void clear() { m.clear(); }
bool empty() const { return m.empty(); }
explicit operator bool() const { return empty(); }
template<class Interface>
operator Interface*() const
{
auto i = m.find(property::id_of<Interface>());
if(i==m.end()) return nullptr;
return dynamic_cast<Interface*>(i->second.get());
}
template<class Interface>
friend aggregate& operator<<(aggregate& s, interface<Interface>* pi)
{ return s.add_interface(pi); }
private:
typedef std::map<unsigned, std::unique_ptr<property> > map_t;
map_t m;
};
}
/// this is a sample on how it can workout
class interface_A: public dynamic::interface<interface_A>
{
public:
virtual void methodA1() =0;
virtual void methodA2() =0;
};
class impl_A1: public interface_A
{
public:
impl_A1() { std::cout<<"creating impl_A1["<<this<<"]"<<std::endl; }
virtual ~impl_A1() { std::cout<<"deleting impl_A1["<<this<<"]"<<std::endl; }
virtual void methodA1() { std::cout<<"interface_A["<<this<<"]::methodA1 on impl_A1 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodA2() { std::cout<<"interface_A["<<this<<"]::methodA2 on impl_A1 in aggregate "<<get_aggregate()<<std::endl; }
};
class impl_A2: public interface_A
{
public:
impl_A2() { std::cout<<"creating impl_A2["<<this<<"]"<<std::endl; }
virtual ~impl_A2() { std::cout<<"deleting impl_A2["<<this<<"]"<<std::endl; }
virtual void methodA1() { std::cout<<"interface_A["<<this<<"]::methodA1 on impl_A2 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodA2() { std::cout<<"interface_A["<<this<<"]::methodA2 on impl_A2 in aggregate "<<get_aggregate()<<std::endl; }
};
class interface_B: public dynamic::interface<interface_B>
{
public:
virtual void methodB1() =0;
virtual void methodB2() =0;
};
class impl_B1: public interface_B
{
public:
impl_B1() { std::cout<<"creating impl_B1["<<this<<"]"<<std::endl; }
virtual ~impl_B1() { std::cout<<"deleting impl_B1["<<this<<"]"<<std::endl; }
virtual void methodB1() { std::cout<<"interface_B["<<this<<"]::methodB1 on impl_B1 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodB2() { std::cout<<"interface_B["<<this<<"]::methodB2 on impl_B1 in aggregate "<<get_aggregate()<<std::endl; }
};
class impl_B2: public interface_B
{
public:
impl_B2() { std::cout<<"creating impl_B2["<<this<<"]"<<std::endl; }
virtual ~impl_B2() { std::cout<<"deleting impl_B2["<<this<<"]"<<std::endl; }
virtual void methodB1() { std::cout<<"interface_B["<<this<<"]::methodB1 on impl_B2 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodB2() { std::cout<<"interface_B["<<this<<"]::methodB2 on impl_B2 in aggregate "<<get_aggregate()<<std::endl; }
};
int main()
{
dynamic::aggregate agg1;
agg1 << new impl_A1 << new impl_B1;
dynamic::aggregate agg2;
agg2 << new impl_A2 << new impl_B2;
interface_A* pa = 0;
interface_B* pb = 0;
pa = agg1; if(pa) { pa->methodA1(); pa->methodA2(); }
pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); }
pa = agg2; if(pa) { pa->methodA1(); pa->methodA2(); }
pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); }
agg2 = std::move(agg1);
pa = agg2; if(pa) { pa->methodA1(); pa->methodA2(); }
pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); }
return 0;
}
是很糟糕。: D
已经做过无数次,不同程度和成功程度。
QT有Qobject,所有与它们相关的东西都是从它派生的。
MFC有一个对象,所有的东西都是从它派生的,就像c++。net一样
我不知道是否有办法让它不那么糟糕,我想如果你像瘟疫一样避免多重继承(这是一个有用的语言特性)并重新实现stdlib会更好。但如果这就是你想要的,那你可能使用了错误的语言。
Java和c#更适合这种编程风格。
#注意,如果我读错了你的问题,请删除这个答案。
查看动态c++
相关文章:
- C++中的动态对象与非动态对象
- 对具有动态分配的内存和析构函数的类对象的引用
- 我有一个对象,它将在整个程序的持续时间内实例化,但一个类成员不会,我应该动态分配它吗?
- 在对象指针上调用 Delete 是否会递归删除其动态分配的成员
- 生成文件:动态源文件名和对象目录
- 我们可以通过 IPC 传递具有动态管理成员的类对象吗?
- 使用动态实例化的对象填充矢量的快速方法
- 如何在 Cheerp/js 中迭代动态命名的对象?
- 销毁C++中动态分配的内存(数组对象)
- 创建动态对象并将其推送到矢量中
- 删除包含包含动态对象的 STL 容器的智能指针
- C++ 将抽象类型的动态分配对象传递给函数并存储在向量中
- 如何在运行时在对象数组中动态追加新对象C++并打印它们
- 将基类分配给派生对象,反之亦然,以C++以及静态和动态对象之间的差异
- 如何访问对象动态数组中的私有成员变量?
- 如果您为类的一个对象动态分配内存作为参数,会发生什么
- Cython 中对象动态大小的数组
- malloc分配的对象动态类型是什么
- C++按属性排序的对象动态数组
- visual C++新与Malloc的对象动态内存阵列