我来自C#背景,现在正试图拿起C ++。我使用一个具有静态成员的抽象类来跟踪该对象类型的总数,以及一个获取计数的静态方法。例如:
class Shape
{
public:
virtual void Draw() = 0;
static int GetShapeCount();
private:
static int mShapeCount;
};
我注意到派生类也能够调用抽象类静态方法,我发现它有点好奇/令人困惑。例如,如果他们能够执行以下操作,可能会有人感到困惑:
Shape *newShape = new Rectangle();
cout << newShape->GetShapeCount();
这是否意味着获得矩形计数或形状计数?我还注意到即使你没有明确地将它称为形状,你仍然可以通过派生类访问静态方法:
Rectangle rectClass = Rectangle();
cout << rectClass.GetShapeCount();
所以我的问题是双重的:
1)为什么/如何可能这一点 2)有没有办法不允许派生类调用抽象类静态方法?
编辑:
我在C#中运行的测试是不正确的,它显示了类似的行为......我觉得静态方法也会落到派生类中似乎很奇怪。它与其他语言似乎一致,我想我只是犯了一个错误。
答案 0 :(得分:3)
不,C ++没有多态静态函数,所以假设static getShapeCount()
被实现为return mShapeCount;
,它将返回基类值。但是,使用CRTP和静态多态可以很容易地模拟这一点。因为从对象而不是类本身调用静态函数不是一个好习惯,所以这就像魅力一样。
我还注意到,即使你没有明确地将它称为形状,你仍然可以通过派生类访问静态方法
您已宣布getShapeCount()
是公开的,不是吗?而你(我想,再次,因为你没有向我们展示足够的代码)已经使用了公共继承。
答案 1 :(得分:2)
Shape *newShape = new Rectangle();
cout << newShape->GetShapeCount();
是一种写cout << Shape::GetShapeCount()
的方式。
作为
Rectangle rectClass = Rectangle();
cout << rectClass.GetShapeCount();
是一种将cout << Rectangle::GetShapeCount()
写成Shape::GetShapeCount()
的方式。
如果您想禁止Rectangle::GetShapeCount()
你可以添加一个删除的功能(C ++ 11):
class Rectangle : public Shape
{
public:
// Previous methods
static int GetShapeCount() = delete; // forbid the usage Rectangle::GetShapeCount()
};
答案 2 :(得分:1)
我注意到派生类也能够调用抽象类静态方法,我发现它有点好奇/令人困惑。
这与C#中的行为相同:派生类可以访问其基类的所有方法,只要它们的可见性(公共,受保护,内部等)允许它。
这是否意味着获得矩形计数或形状计数?
这是形状计数,因为所有派生类共享同一个计数器。
有没有办法不允许派生类调用抽象类静态方法?
是 - 您可以通过将方法设为private
来隐藏派生类的方法。
如果您希望为每个派生类保留单独的对象计数,则可以创建静态map<type_index,int>
,并递增特定类型的计数器。但是,您需要为static
方法提供对调用者类型的访问权限。