gpt4 book ai didi

子类的 C++ 静态成员修饰符

转载 作者:太空宇宙 更新时间:2023-11-04 13:04:05 24 4
gpt4 key购买 nike

考虑以下代码:

#include <stdio.h>
#include <iostream>

/// Header-file
class Base {
public:
virtual void do_something() const =0;

int GetAttrib () const {return constattribute_;};

static const int constattribute_;
};

typedef Base* Derived_Ptr; //<< adress derived classes by their base-class ptr; so no templates for Base

class DerivedA : public Base {
// static const int constattribute_; //<< change this static attribute for all DerivedA class instances and their derivatives

void do_something() const {};
};

class DerivedB : public Base {
// static const int constattribute_; //<< change this static attribute for all DerivedB class instances and their derivatives

void do_something() const {};
};

/// CC-file
using namespace std;

const int Base::constattribute_(0);
const int DerivedA::constattribute_(1); //<<error: no such variable 'constattribute' in class DerivedA
const int DerivedB::constattribute_(2); //<<error: no such variable 'constattribute' in class DerivedB


int main(void) {
Derived_Ptr derivedA = new DerivedA();
Derived_Ptr derivedB = new DerivedB();

cout << derivedA->GetAttrib() << derivedB->GetAttrib() <<endl;
return 0;
};

我的意图是我有一些抽象接口(interface) (Base),它还定义了一个变量,它应该存在于所有派生类中,并且是可检索的。所有类型的子类都应该被强制/能够为此变量重新定义它们的特定值,最好是在类声明期间(毕竟这些值在声明类时已知)。

我想实现代码,而不是改变 main() 程序,以便输出为“12”而不是现在(取消注释代码中的当前行)“00”(这样做会隐藏基类中的字段).

我试图调查此事,有不同的解决方案,但其中许多与我的直觉相反:1. 有些遵循 CRTP 模式,但是如果我想通过 main 中的 base-ptr 来寻址我的子类,这是不可能的。2. 其他解决方案需要为每个派生实例虚拟化“GetAttrib()”函数,这很麻烦,并且修改属性的操作被隐藏在函数定义中。3. 第三种可能性是删除静态模式并将“constattribute_”字段作为常规成员,但这迫使我将其作为参数拖过所有构造函数。

我很确定必须有一些更聪明的方法来做到这一点。任何提示表示赞赏。

最佳答案

使用 CRTP 可能会得到你想要的,假设你不必通过 Base* 访问 GetAttr() 并且可以在没有 Base 本身的 constattribute_ 的情况下离开。只要遵循每个编程问题都可以通过进入另一个间接级别来解决的规则,我在下面做了:

class Base {
public:
virtual void do_something() const = 0;

virtual ~Base() // should define it as you are using Base*
{
}
};

typedef Base* Derived_Ptr;

template<class T>
class BaseConstAttr : public Base
{
public:
int GetAttrib () const
{
return(constattribute_);
};

static const int constattribute_;
};

class DerivedA : public BaseConstAttr<DerivedA>
{
public:
void do_something() const
{
};
};

class DerivedB : public BaseConstAttr<DerivedB>
{
public:
void do_something() const
{
};
};

template<> const int BaseConstAttr<DerivedA>::constattribute_(1);
template<> const int BaseConstAttr<DerivedB>::constattribute_(2);

如果您需要从继承树的顶部到底部的 GettAttr,您可以稍微修改上面的代码,但这将花费您使 GetAttr 成为虚拟的(但仍然只有一个实现):

class Base {
public:
virtual void do_something() const = 0;
virtual int GetAttrib () const = 0;

virtual ~Base() // should define it as you are using Base*
{
}
};

typedef Base* Derived_Ptr;

template<class T>
class BaseConstAttr : public Base
{
public:
int GetAttrib () const
{
return(constattribute_);
};

static const int constattribute_;
};

class DerivedA : public BaseConstAttr<DerivedA>
{
public:
void do_something() const
{
};
};

class DerivedB : public BaseConstAttr<DerivedB>
{
public:
void do_something() const
{
};
};

template<> const int BaseConstAttr<DerivedA>::constattribute_(1);
template<> const int BaseConstAttr<DerivedB>::constattribute_(2);

请注意,我不知道深度继承树(即从 DerivedA 和/或 DerivedB 继承时)的表现有多好(或多坏)。在这种情况下,我可能会从 Base 正下方的继承树中删除 BaseConstAttr,并尝试将其注入(inject)大多数派生类及其前身之间或使用多重继承。

关于子类的 C++ 静态成员修饰符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43098623/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com