Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以在抽象类中有静态数据成员吗?_C++_Abstract Class_Static Members - Fatal编程技术网

C++ 我可以在抽象类中有静态数据成员吗?

C++ 我可以在抽象类中有静态数据成员吗?,c++,abstract-class,static-members,C++,Abstract Class,Static Members,我设计了一系列相关的类,为了能够管理它们,我让它们从一个抽象类派生出来 这些类都需要访问一系列共享资源,我发现自己在每个类中创建了一个指针向量,所有这些指针都是相同的(它们必须是相同的)。似乎在基类中创建一个静态成员会让所有派生类都可以访问这个向量,这意味着我只需要构建一次(在构建之后,它也不会改变,只是查找一下) 我的问题是,如果这是确定的,那么我如何构建它,而不从一个派生类调用“fill the vector”方法 我的想法是这样做 class Resource {}; enumR {RE

我设计了一系列相关的类,为了能够管理它们,我让它们从一个抽象类派生出来

这些类都需要访问一系列共享资源,我发现自己在每个类中创建了一个指针向量,所有这些指针都是相同的(它们必须是相同的)。似乎在基类中创建一个静态成员会让所有派生类都可以访问这个向量,这意味着我只需要构建一次(在构建之后,它也不会改变,只是查找一下)

我的问题是,如果这是确定的,那么我如何构建它,而不从一个派生类调用“fill the vector”方法

我的想法是这样做

class Resource {};

enumR {RES0, RES1};

class AbstractClass
{
    public:
        virtual void OnInit() = 0;
        void static fillVector(Resource* pResource, enumR Resourcename)
            {lResource[Resourcename]=pResource;};
    protected:
        static vector<Resource*> lResource;
};

vector<Resource*> AbstractClass::lResource;

int main()
{
    Resource res0, res1;
    AbstractClass::fillVector(&res0, RES0);
    AbstractClass::fillVector(&res1, RES1);

    return 0;
};
类资源{};
枚举{RES0,RES1};
类抽象类
{
公众:
虚拟void OnInit()=0;
void静态fillVector(资源*pResource,枚举资源名)
{lResource[Resourcename]=pResource;};
受保护的:
静态向量资源;
};
向量抽象类::lResource;
int main()
{
资源res0,res1;
AbstractClass::fillVector(&res0,res0);
AbstractClass::fillVector(&res1,res1);
返回0;
};
然后,当我实例化从AbstractClass派生的任何类的对象时,我可以访问lResource向量,这就是我想要的


这样行吗?很可怕吗?可以吗?

它可以工作,其中work=compile&run

但是,所有子类都将访问相同的静态向量,这意味着每个子类不会有不同的静态向量副本

要更好地解释我的意思,请阅读以下内容:

解决方案:

一种解决方案是将父类设置为模板类,如下所示:

template<T>
class Parent<T> {
    public:
        static std::vector<T> sharedResource_;
}

class ChildA : Parent<ChildA> {
}

class ChildB : Parent<ChildB> {
}
模板
班级家长{
公众:
静态std::向量共享资源;
}
A类:家长{
}
B类:家长{
}
在上面的代码中,您将获得ChildA的所有实例的共享资源,以及ChildB实例之间共享的另一个资源

对吗?

嗯,我认为这不好。与此相关的讨论之一在对以下SO问题的评论中,也在我对该问题的回答中:


更好的解决方案是只创建一个包含向量的对象,然后只实例化一次,并给其他类一个指向它的指针或引用。除非有必要,否则应绝对避免使用静态数据。您可以添加一个静态函数来初始化静态向量:

class AbstractClass
{
    private:
        // Add this
        static vector<Resource*> CreateResources();

    protected:
        static vector<Resource*> lResource;
};

vector<Resource*> AbstractClass::lResource = CreateResources();

vector<Resource*> AbstractClass::CreateResources()
{
    vector<Resource*> resources;

    resources[RES0] = new Resource();
    resources[RES1] = new Resource();

    return resources;
}
class抽象类
{
私人:
//加上这个
静态向量CreateResources();
受保护的:
静态向量资源;
};
vector AbstractClass::lResource=CreateResources();
vector AbstractClass::CreateResources()
{
媒介资源;
资源[RES0]=新资源();
资源[RES1]=新资源();
归还资源;
}

您可以尝试boost::assign::list\u,如下所示:

vector<Resource*> AbstractClass::lResource = list_of( &res0 )( &res1 );
向量抽象类::lResource=list_of(&res0)(&res1);
我这里有几点

  • 您的矢量可能大小为0。这可能会导致一些碰撞。在使用之前,您必须分配它。您可以提供静态或全局初始化
  • 你真的想要一个向量吗?当您使用一些动态内存分配时,Vector是合适的。枚举是静态的。您可以给出一个简单的计数并将其作为数组进行分配
  • 你真的想要一个静态成员吗?静态成员通常在同一类的对象之间共享时使用。您能否使用类中的局部/全局外部对象来满足需求?你也可以在类中创建静态函数吗

因为您正在创建“资源指针”的向量,并且没有预先为对象保留空间,所以您的系统可能会在将来崩溃。为什么?
向量在插入元素时创建一个内存块,并使用相同的块,直到它达到其容量。一旦它达到其容量,并且您插入了一个新元素,vector将分配一个新内存(是以前分配内存的两倍),并将所有现有元素复制到新内存中。由于这是一个“指针”向量,它将使所有引用无效

在这些情况下,我通常会添加一个中间模板层,这样我就有了如下结构:

vector<Resource*> AbstractClass::lResource = list_of( &res0 )( &res1 );
定义抽象接口:

class A
{
public:
virtual ~A(){}

virtual void f() = 0 

virtual A* Clone() const = 0
}
将子级常用的资源放在模板中,并在必要时使用CRTP定义boiler plate函数,使必要的接口函数保持抽象

template<class Derived>
class A_T: public A
{
public:
virtual void f() = 0;

virtual A* Clone const
{
return new Derived(dyn_cast<Derived&>(*this))
}

void ManageRes();

private:
vector myResource;
}
模板
A类:公共A
{
公众:
虚空f()=0;
虚拟克隆常量
{
返回新的派生(dyn_cast(*this))
}
void ManageRes();
私人:
媒介资源;
}
最后,不同的具体类完成了实现,并在必要时对这些资源执行一些特殊的操作

class Child: public A_T<Child>
{
public: 
void foo();
}
类子级:公共A\u T
{
公众:
void foo();
}

“它会工作吗?”。。嗯,你可以试着回答这个问题。很可怕吗?我不这么认为,我认为这很好。它有多可怕取决于你对“抽象”的定义有多严格。有些人认为抽象基类应该只包含抽象函数。其他的则不那么严格。但全局实例不是同样“静态”的吗,即:有问题吗?我认为static==在线程上下文中是有问题的…@rubenvb:他明确表示向量在填充后从未更改。我在想这没什么大不了的。是的,好吧,我只是在做一个学究。我不想上课太多,这就是为什么我回避它。我想我可以在类外实例化向量,并在基类中放置一个指针,然后在每个派生类中指向该指针。