我有一个几何对象的基类,我自己使用但我也希望将该类继承到另一个类中,因为它们共享很多逻辑,所以它是对象的高级版本。基础对象有几个静态创建方法(由于参数冲突不能使用new),我不想继承那些。我能否以某种方式指明那些不被继承?
编辑:包含一个例子
struct Banana {
float length;
Banana() {}
Banana(float length) {
this->length = length;
}
static Banana CreateByHalfLength(float halfLength) {
return Banana(halfLength * 2);
}
};
struct AdvancedBanana : Banana {
float bendAmt;
AdvancedBanana(float length, float bendAmt) {
this->length = length; this->bendAmt = bendAmt;
}
};
我不希望AdvancedBanana :: CreateByHalfLength存在,而我希望Banana :: CreateByHalfLength存在并且可以从课外访问。
答案 0 :(得分:3)
在子项中尝试将redclare函数设为private:
#include <iostream>
class Banana {
public:
float length;
float getLenght(){
return length;
}
void setLenght(float value){
length = value;
}
Banana() {}
Banana(float length) {
this->length = length;
}
static Banana CreateByHalfLength(float halfLength) {
return Banana(halfLength * 2);
}
};
class AdvancedBanana : public Banana {
public:
float bendAmt;
AdvancedBanana(float length, float bendAmt) {
this->length = length; this->bendAmt = bendAmt;
}
private:
static AdvancedBanana CreateByHalfLength(float halfLength);
};
int main()
{
// work
Banana a(1);
a.CreateByHalfLength(1);
AdvancedBanana b(0,1);
//will fail
// b.CreateByHalfLength(1);
};
答案 1 :(得分:1)
你只能这样做,使用AdvancedBanana的私有继承。
FragmentStatePagerAdapter
AdvancedBanana :: CreateByHalfLength应该存在,如果你想要Banana :: CreateByHalfLength存在并且可以从类外部访问。 而且这也不是一个好的解决方案。
另一方面我建议,设计两个或更多课程或从香蕉中取出功能,以满足您的需求。它会是这样的。
#include <stdio.h>
struct Banana {
float length;
Banana() {}
Banana(float length) {
this->length = length;
}
static Banana CreateByHalfLength(float halfLength) {
return Banana(halfLength * 2);
}
};
struct AdvancedBanana : private Banana {
float bendAmt;
AdvancedBanana(float length, float bendAmt) {
this->length = length; this->bendAmt = bendAmt;
}
};
int main()
{
Banana b;
b.CreateByHalfLength(1);
AdvancedBanana bb(1, 2);
//bb.CreateByHalfLength(2);
return 0;
}
答案 2 :(得分:1)
如果要自动限制派生类重载static Banana CreateByHalfLength(float halfLength);
,那么很快就可以将该函数封装在virtual final
方法中。
e.g。
struct Banana {
...
// Create a namesake wrapper for the `static` function and make it final
virtual
Banana CreateByHalfLength(float halfLength) final {
return CreateByHalfLengthImpl(halfLength);
}
static Banana CreateByHalfLengthImpl(float halfLength) {
return Banana(halfLength * 2);
}
};
通过这种安排,现在任何派生类都无法创建类似的函数static
或非static
。
Here is a demo
这种方法的缺点是你要添加virtual
的函数开销以及使用未使用的对象调用。
答案 3 :(得分:-1)
你所说的有点模糊,一个例子会很有用。 特别是因为你使用单词static,并且不清楚它的上下文是什么。
您无法阻止派生类继承基类的所有方法。您可以做的最好的事情是使其成为需要基础对象参数的非成员。然后你必须在调用之前向下转换对象,但你仍然可以调用它。
你的建议似乎违反了Liskov替代原则。这意味着你应该重新考虑你的设计。
而不是B继承自A.你可能想要一个基类Q,A和B都来自它。 [1]
[1] Q是一个笑话,一些圣经学者认为,有一些共同的不完整的书,他们称之为Q,每个福音都是从中复制的。
编辑:附加。
通过这个例子,有些事情更加清晰。 让我对你对C ++的理解做一些基本的修改。你说,由于参数冲突,你有几种静态创建方法。我认为更好地说重载不能解决不同的构造方法。答案非常简单:以两种方式之一扩展过载。 使用枚举或使用类。 您可以通过附加ios :: ate等在流中调用read / append / read-write类型流来看到第一个。
在你的情况下:
enum BCT {halfLength,fullLength,quarterLength ...};
然后呢 static Banana Create(float size,BCT type = fullLength){ 开关(类型) { case fullLength:返回香蕉(大小); case halfLength:返回香蕉(大小* 2); case quarterLength:返回Banana(大小* 4); ... } }
备用版本是使用类来区分参数类型(我相信James Coplien称这些样本)
class FullLength
class HalfLength
class QuarterLength
然后:
static Banana Create(float length); // Full length
static Banana Create(float halfLength, HalfLength &dummy);
static Banana Create(float quarterlength, QuarterLength &dummy);
新类在开销中不添加任何内容,但确实消除了重载歧义。我相信boost / std :: filesystem以这种方式使用它的直接迭代器。
话虽如此,一旦您决定如何创建实例,这些不必是静态成员。他们可以是普通的构造者,这将解决您的问题。在大多数情况下。你仍然无法阻止AdvancedBanana实现半长创建方法,但编码人员会意识到他正在这样做。
关于静态的简要说明,静态成员函数是那些不访问 this 指针或某些语言称为 self 的函数,即它们不访问成员一个特定的例子。事实上,在preC ++ 98天,在他们有静力学之前,人们做的是做一些事情:((Banana *)NULL)->static_function(arguments);
在您的示例中,最好首先使用构造函数。静态构造函数最好留给真正需要的工厂。
另外,在Mido的回复中,行a.CreateByHalfLength(1);
可能编译也可能不编译,我使用了很多语言,有时我会对非法行为感到困惑:(但这表明思路不好。调用静态的正确方法是Banana :: CreateByHalfLength(1);不依赖于实例。