我在头文件中遇到了以下代码:
class Engine
{
public:
void SetState( int var, bool val );
{ SetStateBool( int var, bool val ); }
void SetState( int var, int val );
{ SetStateInt( int var, int val ); }
private:
virtual void SetStateBool(int var, bool val ) = 0;
virtual void SetStateInt(int var, int val ) = 0;
};
Run Code Online (Sandbox Code Playgroud)
对我来说,这意味着Engine从它派生的类或类必须为那些纯虚函数提供实现.但我不认为派生类可以访问这些私有函数以重新实现它们 - 那么为什么要将它们变为虚拟?
在设计界面时,有人建议使用非虚拟界面模式.有人可以简要介绍一下这种模式的好处吗?
我一直在尝试使用奇怪的重复模板模式进行通用的单参数仿函数,并且有两个实现:一个使用模板模板参数工作,另一个我尝试访问接口类中的派生Functor ::类型.在后一个例子中,编译器(gcc 5.4.0)报告
错误:'struct Cube <double>中没有名为' type ' 的类型
template<class T, template<class> class Functor>
class FunctorInterface_1 {
private:
const Functor<T> &f_cref;
public:
FunctorInterface_1() : f_cref(static_cast<const Functor<T>&>(*this)) {}
T operator() ( T val ) const { return f_cref(val); }
}; // FunctorInterface_1 (works)
template<class Functor>
class FunctorInterface_2 {
private:
const Functor &f_cref;
public:
using Ftype = typename Functor::type;
FunctorInterface_2() : f_cref(static_cast<const Functor&>(*this)) {}
Ftype operator() ( Ftype val ) const { return f_cref(val); }
}; // FunctorInterface_2 …Run Code Online (Sandbox Code Playgroud) 在C++中,我经常需要NVI才能在API中获得一致性.不过,在C#中我没有看到它用得那么多.我想知道这是因为C#作为一种语言,提供的功能使得NVI不再需要吗?(尽管如此,我仍然在C#中使用NVI.)
C++私有和受保护的虚方法,有没有使用公共虚方法的正当理由?正在讨论非虚拟接口(NVI)和非公共虚拟功能及其共生关系.Scott Meyers也在Effective C++中说过
有时虚拟功能甚至必须是公开的,但是NVI惯用法无法真正应用.
我没有看到为什么NVI 要求特定于实现的虚拟功能是非公开的?从Herb Sutter的文章Virtuality来看,它是一个很好的做法,例如,将公共(客户端)接口与实现细节(非公共接口)分开是很好的.我想知道的是,如果有任何语言功能我错过了语义上会阻止NVI被应用,如果这些虚拟功能被公开?
例如:
class Engine
{
public:
void SetState( int var, bool val );
{ SetStateBool( int var, bool val ); }
void SetState( int var, int val );
{ SetStateInt( int var, int val ); }
private:
virtual void SetStateBool(int var, bool val ) = 0;
virtual void SetStateInt(int var, int val ) = 0;
};
Run Code Online (Sandbox Code Playgroud)
如果我把带来哪些影响SetStateBool,并SetStateInt在类定义的公共部分?
非虚拟接口惯用法描述了虚拟方法是非公共自定义点的方式,公共方法是非虚拟方法,以允许基类始终控制如何调用自定义点.
这是一个优雅的习语,我喜欢使用它,但如果派生类本身就是一个基类,它是如何工作的
java最终方法和c ++非虚方法有什么不同或相同?怎么样?
在C++中,接口可以由类实现,其所有方法都是纯虚拟的.
这样的类可以是库的一部分,用于描述对象应该实现哪些方法以便能够与库中的其他类一起使用:
class Lib::IFoo
{
public:
virtual void method() = 0;
};
Run Code Online (Sandbox Code Playgroud)
:
class Lib::Bar
{
public:
void stuff( Lib::IFoo & );
};
Run Code Online (Sandbox Code Playgroud)
现在我想使用类Lib :: Bar,所以我必须实现IFoo接口.
为了我的目的,我需要一个完整的相关类,所以我想使用一个基类来保证使用NVI习语的常见行为:
class FooBase : public IFoo // implement interface IFoo
{
public:
void method(); // calls methodImpl;
private:
virtual void methodImpl();
};
Run Code Online (Sandbox Code Playgroud)
非虚拟接口(NVI)习惯用法应该拒绝派生类覆盖实现的公共行为的可能性FooBase::method(),但是由于IFoo使其成为虚拟,所以派生类似乎都有机会覆盖FooBase::method().
如果我想使用NVI成语,除了已经建议的pImpl成语之外我还有什么选择(感谢space-c0wb0y).
我理解非虚方法是静态绑定的,这意味着,据我所知,它在编译时就知道哪个方法将在哪个对象上调用.该决定基于对象的静态类型.令我困惑的是接口(而不是类)和静态绑定.
考虑一下这段代码
public interface IA
{
void f();
}
public class A : IA
{
public void f() { Console.WriteLine("A.f()"); }
}
public class B : A
{
public new void f() { Console.WriteLine("B.f()"); }
}
B b = new B();
b.f(); //calls B.f() //Line 1
IA ia = b as IA;
ia.f(); //calls A.f() //Line 2
Run Code Online (Sandbox Code Playgroud)
演示代码:http://ideone.com/JOVmi
我明白了Line 1.编译器可以知道b.f()将调用,B.f()因为它知道静态类型b …
什么是可接受的术语(如果有的话),用于描述只能虚拟调用的方法以及基础中的其他方法?我偶尔会看到这被称为回调,但这似乎偏离了该术语的原始定义.我甚至不确定这是一种被称为模式的优点,但我正试图在评论我的代码时变得更加精确.谢谢您的帮助!
// Abstract class.
class A {
public:
void run() { while (call()) { /* ... */ } }
private:
virtual bool call() = 0;
};
// Completion/specialization of A.
class B : public A {
private:
// Standard term to indicate this pattern?
bool call();
};
Run Code Online (Sandbox Code Playgroud)
摘要:这似乎被称为非虚拟接口模式,这是模板方法模式的一个特例.感谢Nick和Steven的帮助!
virtual design-patterns private non-virtual-interface template-method-pattern
我的层次结构看起来像这样:
class Base
{
public:
void Execute();
virtual void DoSomething() = 0;
private:
virtual void exec_();
};
class Derived : public Base
{
public:
//DoSomething is implementation specific for classes Derived from Base
void DoSomething();
private:
void exec_();
};
void Base::Execute()
{
// do some work
exec_(); //work specific for derived impl
// do some other work
}
void Derived::DoSomething()
{
//impl dependent so it can only be virtual in Base
}
int main()
{
Derived d;
Base& b = …Run Code Online (Sandbox Code Playgroud) c++ ×10
c# ×3
idioms ×3
inheritance ×2
interface ×2
virtual ×2
class-design ×1
final ×1
java ×1
oop ×1
polymorphism ×1
private ×1
templates ×1