题
反正是有来有一种虚拟的静态部件C++?
例如:
class BaseClass {
public:
BaseClass(const string& name) : _name(name) {}
string GetName() const { return _name; }
virtual void UseClass() = 0;
private:
const string _name;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass("DerivedClass") {}
virtual void UseClass() { /* do something */ }
};
我知道这个例子是微不足道,但如果我有一个向量复杂数据,将始终同所有源类,但是需要从基类的方法?
class BaseClass {
public:
BaseClass() {}
virtual string GetName() const = 0;
virtual void UseClass() = 0;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() {}
virtual string GetName() const { return _name; }
virtual void UseClass() { /* do something */ }
private:
static const string _name;
};
string DerivedClass::_name = "DerivedClass";
这种解决方案没有满足我因为我需要重新实现的成员_name和其访问GetName()每类。在我的情况下,我有几个成员如下_name行为和十分之一源类。
任何想法?
解决方案
这里是一个解决办法:
struct BaseData
{
const string my_word;
const int my_number;
};
class Base
{
public:
Base(const BaseData* apBaseData)
{
mpBaseData = apBaseData;
}
const string getMyWord()
{
return mpBaseData->my_word;
}
int getMyNumber()
{
return mpBaseData->my_number;
}
private:
const BaseData* mpBaseData;
};
class Derived : public Base
{
public:
Derived() : Base(&sBaseData)
{
}
private:
static BaseData sBaseData;
}
BaseData Derived::BaseData = { "Foo", 42 };
其他提示
这似乎是回答的问题-方法的建议似乎是正确的方向去,除了如果你有一个很大的数量的那些共享成员可能想收集他们进入一个结构或类和过去的参数构造的基类。
如果你坚持要求具有"共有的"成员实施为静态的成员得出类,则可以自动生成的代码的源类。XSLT是一个伟大的工具,用于自动生成简单的课程。
在一般情况下,如不显示需要"虚拟静态"的成员,因为为目的(如这些你实际上并不需要继承的而不是你应该使用基类和已经接受了适当价值的构造或许建立一个单一实例的参数为各个"子类"并通过的指针为它避免重复,共享数据。另一个类似的方法是使用的模板和通过作为模板参数的一类,提供所有相关价值的(这是通常被称为"政策"模式)。
结束-为的目的原来的实例,不需要这样的"虚拟静态"的成员。如果你仍然认为它们是需要你的代码写的,请尽量详细,并添加更多的上下文。
如我以上所述:
class BaseClass {
public:
BaseClass(const Descriptor& desc) : _desc(desc) {}
string GetName() const { return _desc.name; }
int GetId() const { return _desc.Id; }
X GetX() connst { return _desc.X; }
virtual void UseClass() = 0;
private:
const Descriptor _desc;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass(Descriptor("abc", 1,...)) {}
virtual void UseClass() { /* do something */ }
};
class DerDerClass : public BaseClass {
public:
DerivedClass() : BaseClass("Wowzer", 843,...) {}
virtual void UseClass() { /* do something */ }
};
我想阐述这种方案,以及可能得到解决de-初始化问题:
有一个小的变化,可以实施的设计上所述,不一定是创建一个新的实例"描述"对于每个实例中的一个源类。
你可以创建一个单独的目的,DescriptorMap,即将举行的单个实例中的每一个描述,并利用它在建造所衍生的对象是这样的:
enum InstanceType {
Yellow,
Big,
BananaHammoc
}
class DescriptorsMap{
public:
static Descriptor* GetDescriptor(InstanceType type) {
if ( _instance.Get() == null) {
_instance.reset(new DescriptorsMap());
}
return _instance.Get()-> _descriptors[type];
}
private:
DescriptorsMap() {
descriptors[Yellow] = new Descriptor("Yellow", 42, ...);
descriptors[Big] = new Descriptor("InJapan", 17, ...)
...
}
~DescriptorsMap() {
/*Delete all the descriptors from the map*/
}
static autoptr<DescriptorsMap> _instance;
map<InstanceType, Descriptor*> _descriptors;
}
现在我们可以这样做:
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass(DescriptorsMap.GetDescriptor(InstanceType.BananaHammoc)) {}
virtual void UseClass() { /* do something */ }
};
class DerDerClass : public BaseClass {
public:
DerivedClass() : BaseClass(DescriptorsMap.GetDescriptor(InstanceType.Yellow)) {}
virtual void UseClass() { /* do something */ }
};
在执行结束时,当C runtime执行uninitializations,它还要求析构的静态目的、包括我们的autoptr,其中删除我们的实例DescriptorsMap.
所以现在我们有一个单一实例的每一个描述,也被删除末尾的执行。
请注意,如果唯一的目的衍生类提供有关"描述符"的数据(即而不是虚拟实施的功能),那么你应该做得基类非抽象,只是创造一个实例,与适当的描述符。
我同意Hershi的建议使用一个模板,作为"基类"。从你所描述的,这听起来更像是一个使用的模板,而不是子类化。
你可以创建一个模板如下(没有试图的编译本):
template <typename T>
class Object
{
public:
Object( const T& newObject ) : yourObject(newObject) {} ;
T GetObject() const { return yourObject } ;
void SetObject( const T& newObject ) { yourObject = newObject } ;
protected:
const T yourObject ;
} ;
class SomeClassOne
{
public:
SomeClassOne( const std::vector& someData )
{
yourData.SetObject( someData ) ;
}
private:
Object<std::vector<int>> yourData ;
} ;
这会让你使用的模板类方法的修改数据为需要从你定制的课程,使用的数据和分享的各个方面的模板类。
如果你在意图上使用的继承,然后你可能需要诉诸"欢乐"的使用void*指针在你的基类和处理铸造,等等。
然而,根据您的解释,这似乎是你需要的模板,而不继承。
@Hershi:这种做法的问题是,每个实例的每一个源类具有数据的副本,这可能是昂贵的,在一些方式。
也许你可以试试这样的事情(我吐珠没有编制实例,但这个想法应该被清除)。
#include <iostream>
#include <string>
using namespace std;
struct DerivedData
{
DerivedData(const string & word, const int number) :
my_word(word), my_number(number) {}
const string my_word;
const int my_number;
};
class Base {
public:
Base() : m_data(0) {}
string getWord() const { return m_data->my_word; }
int getNumber() const { return m_data->my_number; }
protected:
DerivedData * m_data;
};
class Derived : public Base {
public:
Derived() : Base() {
if(Derived::s_data == 0) {
Derived::s_data = new DerivedData("abc", 1);
}
m_data = s_data;
}
private:
static DerivedData * s_data;
};
DerivedData * Derived::s_data = 0;
int main()
{
Base * p_b = new Derived();
cout getWord() << endl;
}
关于后续行动的问题上删除静态物体:唯一的解决办法是使用一个聪明的指针,类似的东西的 提高共用针.
这听起来如果你想要避免重复代码在叶类,那么,为什么不只是获得一个中间基类基类。这种中间类可以保持静态数据,以及所有您的叶子类从中间基类。这预先假定一个静态片的数据,举行所有派生的课程是需要的,这似乎很自己的例子。