这是一个有点离奇的问题.我的目标是理解语言设计决策并确定C++中反射的可能性.
为什么C++语言委员会不会在语言中实现反思?对于不在虚拟机上运行的语言(如java),反射是否太难?
如果要实现C++的反射,那么挑战是什么?
我想反射的使用是众所周知的:编辑器可以更容易编写,程序代码更小,可以为单元测试生成模拟等等.但是,如果你也可以对反射的使用发表评论,那就太棒了.
我希望能够内省一个C++类的名称,内容(即成员及其类型)等.我在这里说的是原生C++,而不是托管C++,它有反射.我意识到C++使用RTTI提供一些有限的信息.哪些额外的库(或其他技术)可以提供此信息?
假设我有一些每类数据:(AandB.h)
class A
{
public:
static Persister* getPersister();
}
class B
{
public:
static Persister* getPersister();
}
Run Code Online (Sandbox Code Playgroud)
......还有很多课程.我想做的事情如下:
persistenceSystem::registerPersistableType( A::getPersister() );
persistenceSystem::registerPersistableType( B::getPersister() );
...
persistenceSystem::registerPersistableType( Z::getPersister() );
Run Code Online (Sandbox Code Playgroud)
......为每个班级.
我的问题是:有没有办法自动构建每类数据列表,这样我就不必枚举大块中的每个类型(如上例所示)?
例如,您可以这样做的一种方法是:(AutoRegister.h)
struct AutoRegisterBase
{
virtual ~AutoRegisterBase() {}
virtual void registerPersist() = 0;
static AutoRegisterBase*& getHead()
{
static AutoRegisterBase* head= NULL;
return head;
}
AutoRegisterBase* next;
};
template <typename T>
struct AutoRegister : public AutoRegisterBase
{
AutoRegister() { next = getHead(); getHead() = this; }
virtual void registerPersist()
{
persistenceSystem::registerPersistableType( T::getPersister() …Run Code Online (Sandbox Code Playgroud) 我一直在研究和测试一个基于这里描述的自我注册的抽象工厂:
在我的所有测试用例中,它都像魅力一样工作,并提供我想要的功能和重用.
使用cmake在我的项目中链接这个工厂一直很棘手(尽管它似乎更像是一个问题).
我有相同的base.hpp,derivedb.hpp/cpp和一个等效的deriveda.hpp/cpp链接的示例.在main中,我只是实例化工厂并调用createInstance()两次,每次使用"DerivedA"和"DerivedB".
该行创建的可执行文件:
g++ -o testFactory main.cpp derivedb.o deriveda.o
Run Code Online (Sandbox Code Playgroud)
按预期工作.将我的派生类移动到一个库中(使用cmake,但我也单独用ar测试过它),然后链接失败:
ar cr libbase.a deriveda.o derivedb.o
g++ -o testFactory libbase.a main.cpp
Run Code Online (Sandbox Code Playgroud)
只调用第一个静态实例化(来自derivedA.cpp)而从不调用第二个静态实例化,即
// deriveda.cpp (if listed first in the "ar" line, this gets called)
DerivedRegister<DerivedA> DerivedA::reg("DerivedA");
// derivedb.cpp (if listed second in the "ar" line, this does not get called)
DerivedRegister<DerivedB> DerivedB::reg("DerivedB");
Run Code Online (Sandbox Code Playgroud)
请注意,在ar行中交换两个调用仅调用derivedb.cpp静态实例化,而不调用deriveda.cpp实例化.
我是否遗漏了一些使用ar或静态库的东西,这些库在某种程度上与C++中的静态变量不相称?
我可以通过提取存储在字符串中的类名来在运行时创建类的对象吗?
例如:我想创建和类的对象QButton一样
QString strClassName = "QButton";
QButton *pBtn = new strClassName();
Run Code Online (Sandbox Code Playgroud)
我想读取所有控件的xml文件,并使用这种方式在运行时实例化它们.
我已经读过Pimpl有利于二进制兼容性,接口有利于轻松切换实现.我需要结合这两种技术,以便我的应用程序能够通过配置文件切换底层实现.
以下是我当前设计的布局:
Foo类:提供面向客户的API,我很担心ABI兼容性这里
一流的IFoo:接口类(所有的纯虚方法,虚析构函数)
类Vendor1Foo:实现IFoo的,使用的供应商1的库
类Vendor2Foo:实现IFoo的,使用供应商2的图书馆
通过不使用pimpl并严格使用接口,客户端代码可能如下所示:
IFoo* foo = new Vendor1Foo();
Run Code Online (Sandbox Code Playgroud)
问题是我的客户端代码根本无法了解Vendor1或Vendor2,而Foo只是我必须执行此操作的众多类之一.
我正在尝试做的所有概念如下:
class foo
{
private:
QScopedPointer<IFoo> pimpl;
void initImpl(); // Reads from QSettings and initializes pimpl
}
Run Code Online (Sandbox Code Playgroud)
有什么想法可以优雅地解决这个问题吗?
我希望能够提出一些宏或模板类/方法来帮助标准化我如何处理这个并最大限度地减少违反DRY.
模板类可以作为一个辅助性PIMPL像香草萨特的大上广义PIMPL方法对C++ 11:herbsutter.com/gotw/_101,它也必须包含逻辑实例根据配置的正确实施
这里有pimpl成语,桥梁模式和工厂模式的元素.在上面的例子中,initImpl()可以被认为是一个工厂方法.我正在寻找可能会或可能不会使用所有这些模式的解决方案.
我已经看过c ++ pimpl习语:实现取决于模板参数以及SO上的大多数pimpl习语问题.标题似乎很有希望,但它对我的特定用例没有帮助.
我不能使用C++ 11并使用Qt. D-Pointers无法解决我的问题,因为它们绑定到单个实现.
假设我有一个类的层次结构:
class Shape {
};
class Circle : public Shape {
}
class Square : public Shape {
}
... hundreds of other shapes continue on...
Run Code Online (Sandbox Code Playgroud)
当给定形状类的名称作为字符串时,我需要实例化该类的对象.
在java中,我可以做这样的事情(伪代码!)
Shape createShape(String name) {
return new Class.forName(name);
}
Run Code Online (Sandbox Code Playgroud)
但是在C++中,我必须这样做:(伪代码!)
Shape * createShape(const string &name) {
if (name.compare("Circle") == 0) {
return new Circle();
}
else if (name.compare("Square") == 0) {
return new Square();
}
else if ... //hundreds of else if continues, one for each shape
}
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法在C++中处理这样的情况?
在面试中我被问到一个问题.
因此我有一个函数void f(std::string),我称之为函数f("int").所以我的函数必须int x在它的体内创建一个局部.有没有办法从中获取类型const char*.我知道boost::mpl::vector确实可以解决这类问题.谁能告诉我这项技术?
我有一个容器,它包含一堆指向基类的指针,以及一个接受一些输入并返回一个类的函数,该类是基类的子类.它返回的子类取决于输入.
现在,我有一个像这样的巨型开关语句:
class Base { ... }
class A : public Base { ... }
class B : public Base { ... }
...
class Z : public Base { ... }
Base* depends(int input) {
switch (input) {
case 1:
return new A(...);
case 2:
return new B(...);
...
case 26:
return new Z(...);
default:
...
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道是否有更好的方法来设计它.我不知道很多"设计模式"(我认为这就是他们所谓的)所以我不知道是否有一种(明显的)更好的方法来设计它.
c++ inheritance construction class-hierarchy switch-statement
可能重复:
有没有办法从保存其类名的字符串中实例化对象?
在C++中,我想让我的用户输入要在运行时创建的对象类型名称,并且,根据我从它们获得的字符串,程序将实例化正确的对象(简而言之,我正在实现工厂方法图案).但是,如果程序必须支持新的对象类型,则不允许修改现有代码.
那么是否有可能从方法中删除所有if ... else if ... else if ...的东西,并且仍然让我的程序实例化特定产品类型的正确对象(在众多中,只有已知的在编译时)?
我的搜索给了我这个链接:有没有办法从持有类名的字符串中实例化对象?它似乎是我想要的,但我根本无法理解代码.
任何帮助将非常感激.
c++ ×10
reflection ×3
qt ×2
algorithm ×1
class ×1
cmake ×1
construction ×1
factory ×1
g++ ×1
inheritance ×1
interface ×1
oop ×1
pimpl-idiom ×1
qt4 ×1
sfinae ×1
stdstring ×1
templates ×1
types ×1
unix-ar ×1