Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 调用修饰基类时访问不明确_C++_Templates_Decorator - Fatal编程技术网

C++ 调用修饰基类时访问不明确

C++ 调用修饰基类时访问不明确,c++,templates,decorator,C++,Templates,Decorator,我有一个类,可以用一组附加模板来修饰它,以提供额外的功能。每个加载项都需要能够调用基类,用户需要能够调用基类(直接调用或使用CMyClass作为代理)。 不幸的是,编译器无法分辨我调用的是哪个基类,并且会出现不明确的访问错误 template< class T > class AddOn_A : public T { public: AddOn_A( int x ) : T( x ) {}; int AddOne() { T* p

我有一个类,可以用一组附加模板来修饰它,以提供额外的功能。每个加载项都需要能够调用基类,用户需要能够调用基类(直接调用或使用CMyClass作为代理)。 不幸的是,编译器无法分辨我调用的是哪个基类,并且会出现不明确的访问错误

template< class T >
class AddOn_A : public T
{
public: 
    AddOn_A( int x ) : T( x ) 
    {};

    int AddOne()
    {
        T* pT = static_cast< T* >( this );
        return pT->GetValue() + 1;
    };
};

template< class T >
class AddOn_B : public T
{
public: 
    AddOn_B( int x ) : T( x ) 
    {};

    int AddTwo()
    {
        T* pT = static_cast< T* >( this );
        return pT->GetValue() + 2;
    };
};

class CBase
{
public:
    explicit CBase( int x ) : x_( x ) 
    {
    };

    int GetValue()
    {
        return x_;
    };

private:
    int x_;
};

// define an empty AddOn
template< class > struct empty {};

// forward declaration and Add-On defaults
template< template< class > class AddOn1 = empty,
          template< class > class AddOn2 = empty,
          template< class > class AddOn3 = empty >
class CMyClass;

// specialized template for the default case
template<> class CMyClass< empty, empty, empty > : public CBase
{
public:
    CMyClass( int x ) : CBase( x ) 
    {};
};

// actual definition
template< template< class > class AddOn1,
          template< class > class AddOn2,
          template< class > class AddOn3 >
class CMyClass : public AddOn1< CBase >,
                 public CMyClass< AddOn2, AddOn3 >
{
public:
    CMyClass( int x ) : AddOn1< CBase >( x ),
                        CMyClass< AddOn2, AddOn3 >( x )
    {};
};

int _tmain( int argc, _TCHAR* argv[] )
{
    CMyClass< AddOn_A > A( 100 );

    // error C2385: ambiguous access of 'GetValue'
    //     1>        could be the 'GetValue' in base 'CBase'
    //     1>        or could be the 'GetValue' in base 'CBase'
    _ASSERT( A.GetValue() == 100 );

    // error C2385: ambiguous access of 'GetValue'
    //     1>        could be the 'GetValue' in base 'CBase'
    //     1>        or could be the 'GetValue' in base 'CBase'
    _ASSERT( A.AddOne() == A.GetValue() + 1 );

    // works
    _ASSERT( A.AddOne() == 101 );

    CMyClass< AddOn_A, AddOn_B > AB( 100 );

    // same errors as above
    _ASSERT( AB.GetValue() == 100 );

    // same errors as above
    _ASSERT( AB.AddTwo() == AB.GetValue() + 2 );

    // works
    _ASSERT( AB.AddTwo() == 102 );

    return 0;
}
模板
类插件A:公共T
{
公众:
插件A(int x):T(x)
{};
int AddOne()
{
T*pT=静态施法(本);
返回pT->GetValue()+1;
};
};
模板
类加载项:公共T
{
公众:
插件B(int x):T(x)
{};
int AddTwo()
{
T*pT=静态施法(本);
返回pT->GetValue()+2;
};
};
C类数据库
{
公众:
显式CBase(int x):x_x(x)
{
};
int GetValue()
{
返回x;
};
私人:
int x_2;;
};
//定义一个空插件
模板struct empty{};
//转发声明和附加默认值
templateclass AddOn1=空,
模板class AddOn2=空,
模板class AddOn3=空>
类CMyClass;
//默认情况下的专用模板
模板类CMyClass:公共CBase
{
公众:
CMyClass(intx):CBase(x)
{};
};
//实际定义
模板class AddOn1,
模板class AddOn2,
模板class AddOn3>
类CMyClass:public AddOn1,
公共CMyClass
{
公众:
CMyClass(intx):AddOn1(x),
CMyClass(x)
{};
};
int _tmain(int argc,_TCHAR*argv[]
{
CMyClassA(100);
//错误C2385:对“GetValue”的访问不明确
//1>可能是基“CBase”中的“GetValue”
//1>或可以是基本“CBase”中的“GetValue”
_断言(A.GetValue()==100);
//错误C2385:对“GetValue”的访问不明确
//1>可能是基“CBase”中的“GetValue”
//1>或可以是基本“CBase”中的“GetValue”
_断言(A.AddOne()==A.GetValue()+1);
//工作
_断言(A.AddOne()==101);
CMyClassAB(100);
//与上述错误相同
_断言(AB.GetValue()==100);
//与上述错误相同
_断言(AB.AddTwo()==AB.GetValue()+2);
//工作
_断言(AB.AddTwo()==102);
返回0;
}
有人能指出我可能做错了什么吗

谢谢,
PaulH

既然我开始使用Decorator方法,我不妨:)

编辑:让我们添加要解决的附加值

这里的问题是多重继承。跟踪这样一个图并不容易,但如果仔细观察,就会发现
CMyClass
从CBase继承了两次


  • CMyClass
    不是一个完整的答案,所以我将添加这个作为注释:CMyClass继承CBase两次。一个通过插件A,一个通过CMyClass。虚拟继承可能是有用的;只是层次结构有问题,见下文:)谢谢你的解释。我在前面尝试使用模板递归来避免为每个附加组件创建专门化。(实际的程序将有11个)我还没有找到一种方法来正确实现您介绍的Decorator模式。有吗?或者,我是否被困在为每个人创建专门化?谢谢,保罗
    // Note that the static_cast are completely unnecessary
    // If you inherit from T then you can freely enjoy
    // its public and protected methods
    template< class T >
    class AddOn_A : public T
    {
    public:
        enum { AddOnValues = T::AddOnValues | 0x01 }; // this hides T::AddOnValues
    
        AddOn_A( int x ) : T( x ) {};
    
        int AddOne()
        {
            return this->GetValue() + 1;
        };
    };
    
    template< class T >
    class AddOn_B : public T
    {
    public:
        enum { AddOnValues = T::AddOnValues | 0x02 }; // this hides T::AddOnValues
    
        AddOn_B( int x ) : T( x ) {};
    
        int AddTwo()
        {
            return this->GetValue() + 2;
        };
    };
    
    class CBase
    {
    public:
        enum { AddOnValues = 0x00 };
    
        explicit CBase( int x ) : x_( x ) {}
        virtual ~CBase() {} // virtual destructor for inheritance
    
        int GetValue() const { return x_; }; // const method
    
    private:
        int x_;
    };
    
    // First, the typedef approach
    typedef AddOn_B< AddOn_A< CBase > > CMyClass;
    CMyClass myObject(3);
    std::cout << myObject.GetValue() << std::endl;
    std::cout << myObject.AddOne() << std::endl;
    std::cout << myObject.AddTwo() << std::endl;
    
     // I want more!
     template < class T >
     class CMyClassImpl: public T
     {
       // Whatever you want
     };
    
     CMyClassImpl< AddOn_B< AddOn_A< CBase > > > myObject(3);
    
     // Even better
     template <>
     class CMyClass: public CMyClassImpl < CBase > {};
    
     template < template <class> class AddOn1>
     class CMyClass: public CMyClassImpl <AddOn1 < CBase > > {};
    
     template < template <class> class AddOn1,
                template <class> class AddOn2 >
     class CMyClass: public CMyClassImpl < AddOn2 < AddOn1< CBase > > > {};
    
     template < template <class> class AddOn1,
                template <class> class AddOn2,
                template <class> class AddOn3 >
     class CMyClass: public CMyClassImpl < AddOn3 < AddOn2< AddOn1< CBase > > > > {};
    
     // Go on with as much specializations as you wish
    
     CMyClass < AddOn_A, AddOn_B > myObject(3);