C++中的静态抽象方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3313754/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
static abstract methods in c++
提问by pm100
I have an abstract base class
我有一个抽象基类
class IThingy
{
virtual void method1() = 0;
virtual void method2() = 0;
};
I want to say - "all classes providing a concrete instantiation must provide these static methods too"
我想说 - “所有提供具体实例化的类也必须提供这些静态方法”
I am tempted to do
我很想做
class IThingy
{
virtual void method1() = 0;
virtual void method2() = 0;
static virtual IThingy Factory() = 0;
};
I know that doesnt compile, and anyway its not clear how to use it even if it did compile. And anyway I can just do
我知道这不会编译,无论如何它不清楚如何使用它,即使它确实编译了。无论如何我可以做
Concrete::Factory(); // concrete is implementation of ITHingy
without mentioning Factory in the base class at all.
根本没有在基类中提到工厂。
But I feel there should be some way of expressing the contract I want the implementations to sign up to.
但我觉得应该有某种方式来表达我希望实现签署的合同。
Is there a well known idiom for this? Or do I just put it in comments? Maybe I should not be trying to force this anyway
这有一个众所周知的成语吗?或者我只是把它放在评论中?也许我不应该试图强迫这样做
Edit: I could feel myself being vague as I typed the question. I just felt there should be some way to express it. Igor gives an elegant answer but in fact it shows that really it doesn't help. I still end up having to do
编辑:当我输入问题时,我会觉得自己很模糊。我只是觉得应该有某种方式来表达它。伊戈尔给出了一个优雅的答案,但实际上它表明它确实无济于事。我还是不得不做
IThingy *p;
if(..)
p = new Cl1();
else if(..)
p = new Cl2();
else if(..)
p = new Cl3();
etc.
I guess reflective languages like c#, python or java could offer a better solution
我想像 c#、python 或 java 这样的反射语言可以提供更好的解决方案
回答by Igor Zevaka
The problem that you are having is partly to do with a slight violation a single responsibility principle. You were trying to enforce the object creation through the interface. The interface should instead be more pure and only contain methods that are integral to what the interface is supposed to do.
您遇到的问题部分与轻微违反单一责任原则有关。您试图通过界面强制创建对象。相反,接口应该更纯粹,并且只包含与接口应该做的事情不可或缺的方法。
Instead, you can take the creation out of the interface (the desired virtual static
method) and put it into a factory class.
相反,您可以从接口(所需的virtual static
方法)中取出创建并将其放入工厂类中。
Here is a simple factory implementation that forces a factory method on a derived class.
这是一个简单的工厂实现,它在派生类上强制使用工厂方法。
template <class TClass, class TInterface>
class Factory {
public:
static TInterface* Create(){return TClass::CreateInternal();}
};
struct IThingy {
virtual void Method1() = 0;
};
class Thingy :
public Factory<Thingy, IThingy>,
public IThingy {
//Note the private constructor, forces creation through a factory method
Thingy(){}
public:
virtual void Method1(){}
//Actual factory method that performs work.
static Thingy* CreateInternal() {return new Thingy();}
};
Usage:
用法:
//Thingy thingy; //error C2248: 'Thingy::Thingy' : cannot access private member declared in class 'Thingy'
IThingy* ithingy = Thingy::Create(); //OK
By derinving from Factory<TClass, TInterface>
, the derived class is forced to have a CreateInternal method by the compiler. Not deifining it will result in an error like this:
通过从Factory<TClass, TInterface>
派生,编译器强制派生类具有 CreateInternal 方法。不定义它会导致这样的错误:
error C2039: 'CreateInternal' : is not a member of 'Thingy'
错误 C2039:“CreateInternal”:不是“Thingy”的成员
回答by jpalecek
There is no sure way to prescribe such a contract in C++, as there is also no way to use this kind of polymorphism, since the line
在 C++ 中没有确定的方法来规定这样的契约,因为也没有办法使用这种多态性,因为行
Concrete::Factory()
is always a static compile-time thing, that is, you cannot write this line where Concrete
would be a yet unknown client-provided class.
总是一个静态编译时的东西,也就是说,你不能Concrete
在一个未知的客户端提供的类的地方写这一行。
You can make clients implement this kind of "contract" by making it more convenient than not providing it. For example, you could use CRTP:
你可以让客户执行这种“合同”,让它比不提供更方便。例如,您可以使用 CRTP:
class IThingy {...};
template <class Derived>
class AThingy : public IThingy
{
public:
AThingy() { &Derived::Factory; } // this will fail if there is no Derived::Factory
};
and tell the clients to derived from AThingy<their_class_name>
(you could enforce this with constructor visibility tweaking, but you cannot ensure the clients don't lie about their_class_name
).
并告诉客户从AThingy<their_class_name>
(您可以通过构造函数可见性调整来强制执行此操作,但您不能确保客户不会说谎their_class_name
)。
Or you could use the classic solution, create a separate hierarchy of factory classes and ask the clients to provide their ConcreteFactory
object to your API.
或者您可以使用经典解决方案,创建一个单独的工厂类层次结构,并要求客户将他们的ConcreteFactory
对象提供给您的 API。
回答by Nathan Ernst
Static methods cannot be made virtual (or abstract, for that matter) in C++.
静态方法不能在 C++ 中成为虚拟的(或抽象的,就此而言)。
To do what you're intending, you can have have an IThingy::factory
method that returns a concrete instance, but you need to somehow provide a means for factory to create the instance. For instance, define a method signature like IThing* (thingy_constructor*)()
and have a static call in IThingy
that you can pass such a function to that defines how IThingy
will construct the factory instance. Then, in a dependent library or class, you can call this method with an appropriate function that, in turn, nows how to properly construct an object implementing your interface.
为了实现您的意图,您可以拥有一个IThingy::factory
返回具体实例的方法,但您需要以某种方式为工厂提供一种创建实例的方法。例如,定义一个方法签名,例如IThing* (thingy_constructor*)()
并有一个静态调用IThingy
,您可以将这样的函数传递给定义如何IThingy
构造工厂实例的函数。然后,在依赖库或类中,您可以使用适当的函数调用此方法,而该函数又是如何正确构造实现您的接口的对象的。
Supposing you haven't had your factory 'initializer' called, you'd want to take appropriate action, such as throwing an exception.
假设您还没有调用工厂“初始化程序”,您需要采取适当的措施,例如抛出异常。