前几天我查看了一些代码,我遇到了:
static {
...
}
Run Code Online (Sandbox Code Playgroud)
来自C++,我不知道为什么会这样.它不是一个错误,因为代码编译得很好.什么是"静态"代码块?
我有一个文件:Base.h
class Base;
class DerivedA : public Base;
class DerivedB : public Base;
/*etc...*/
Run Code Online (Sandbox Code Playgroud)
和另一个文件:BaseFactory.h
#include "Base.h"
class BaseFactory
{
public:
BaseFactory(const string &sClassName){msClassName = sClassName;};
Base * Create()
{
if(msClassName == "DerivedA")
{
return new DerivedA();
}
else if(msClassName == "DerivedB")
{
return new DerivedB();
}
else if(/*etc...*/)
{
/*etc...*/
}
};
private:
string msClassName;
};
/*etc.*/
Run Code Online (Sandbox Code Playgroud)
有没有办法以某种方式将此字符串转换为实际类型(类),以便BaseFactory不必知道所有可能的Derived类,并为每个类都有if()?我可以用这个字符串生成一个类吗?
我认为这可以通过Reflection在C#中完成.C++中有类似的东西吗?
假设我们有一个(玩具)C++类,如下所示:
class Foo {
public:
Foo();
private:
int t;
};
Run Code Online (Sandbox Code Playgroud)
由于没有定义析构函数,因此C++编译器应该自动为类创建一个析构函数Foo.如果析构函数不需要清理任何动态分配的内存(也就是说,我们可以合理地依赖编译器给我们的析构函数),那么将定义一个空的析构函数,即.
Foo::~Foo() { }
Run Code Online (Sandbox Code Playgroud)
做与编译器生成的一样的事情?那个空构造函数怎么样 - 也就是说,Foo::Foo() { }?
如果存在差异,它们存在于何处?如果没有,一种方法优于另一种方法吗?
我有一个带有一些静态成员的类,我想运行一些代码来初始化它们(假设这段代码不能转换成简单的表达式).在Java中,我会这样做
class MyClass {
static int myDatum;
static {
/* do some computation which sets myDatum */
}
}
Run Code Online (Sandbox Code Playgroud)
除非我弄错了,C++不允许这样的静态代码块,对吧?我应该做什么呢?
我想要解决以下两个选项:
对于第二种选择,我在考虑:
class StaticInitialized {
static bool staticsInitialized = false;
virtual void initializeStatics();
StaticInitialized() {
if (!staticsInitialized) {
initializeStatics();
staticsInitialized = true;
}
}
};
class MyClass : private StaticInitialized {
static int myDatum;
void initializeStatics() {
/* computation which sets myDatum */
}
};
Run Code Online (Sandbox Code Playgroud)
但这是不可能的,因为C++(目前?)不允许初始化非const静态成员.但是,至少可以通过表达式将静态块的问题减少到静态初始化的问题......
我使用静态全局变量构造函数作为方便注册函数的技巧,这个想法是这样的:
typedef int (*FuncPtr)(int);
struct RegHelper
{
RegHelper(const char * Name, FuncPtr Func)
{
Register(Name, Func);
}
}
#define REGISTER(func) RegHelper gRegHelper_ ## func (#func, func);
Run Code Online (Sandbox Code Playgroud)
现在我可以这样注册函数(我用它来实现某种反射):
int Foo(int a)
{
return a * 123;
}
REGISTER(Foo)
int Bar(int a)
{
return a * 456;
}
REGISTER(Bar)
Run Code Online (Sandbox Code Playgroud)
问题是,如果我在静态库中使用它,有时链接器会检测到编译单元没有被使用,并且它会丢弃整个内容.所以全局变量没有构造,函数没有注册......
我的问题是:我可以做些什么来解决这个问题?在初始化期间调用每个编译单元中的虚函数似乎触发了全局变量的构造,但这并不觉得非常安全.还有其他建议吗?
我的问题类似于这些,但似乎并没有完全相关:
我得到的是这样的:
struct thingy;
struct container
{
static container& instance(); // singleton
int register_thingy(thingy*);
};
struct thingy
{
virtual ~thingy() {}
virtual int id() const = 0;
};
//template trick to force registration.
template < typename Derived >
struct registered_thingy : thingy
{
registered_thingy() : my_id(my_static_id) {}
int id() const { return my_id; }
private:
int my_id;
static int my_static_id;
}
template < typename Derived >
int registered_thingy<Derived>::my_static_id =
container::instance().register_thingy(new Derived);
Run Code Online (Sandbox Code Playgroud)
现在,concrete_thingy.cpp我在一个文件中:
struct my_concrete_thingy : registered_thingy<my_concrete_thingy> …Run Code Online (Sandbox Code Playgroud) 正如我理解标准一样,一个简单的析构函数是一个隐式声明的析构函数,它的类只有基本和非静态成员和简单的析构函数.鉴于此定义的递归性,在我看来,唯一的"递归停止"条件是找到具有非隐式声明的析构函数的基础或非静态成员(即用户声明).如果这是正确的,那应该意味着一个简单的析构函数是"不必做任何事情",因此它将被声明(隐式)但没有定义.用另一种方式说:根据标准定义,隐含定义的析构函数(即"它做某事")是不是很简单?
对不起那种愚蠢的问题,但我想在脑海中澄清一些事情......
c++ ×6
destructor ×2
java ×2
linker ×2
class ×1
constructor ×1
equivalent ×1
factory ×1
inheritance ×1
oop ×1
static ×1
static-block ×1