2014-02-08 53 views
1

是否可以启用,禁用类成员函数?C++启用,禁用类成员函数?

情况: 我有一个类有两种类型。每个类型都有自己的构造函数。一个类型需要一个不能有另一个类型的函数。

例子:

class A { 
    enum struct TypeEnum : int { 
     TYPE_1 = 1, 
     TYPE_2 = 2 
    }; 
    const TypeEnum type; 

    int x; 


    A(void) : type(TypeEnum::TYPE_1) { } 
    A(int _x) : type(TypeEnum::TYPE_2) { 
     x = _x; 
    } 


    // function only for Type 2 
    void A::operator += (const int& n) { 
     x = x + n; 
    } 
}; 

int main() { 
    A test1 = new A(); 
    A test2 = new A(1); 

    test1 += 5; // compiler error should be here 
    test2 += 5; // OK 

    return 0; 
} 

是哪里的东西可能是这样的:

class A { 
    enum struct TypeEnum : int { 
     TYPE_1 = 1, 
     TYPE_2 = 2 
    }; 
    const TypeEnum type; 

    int x; 


    A(void) : type(TypeEnum::TYPE_1) { } 
    A(int _x) : type(TypeEnum::TYPE_2) { 
     x = _x; 
    } 


    // Is somethig like this realy impossible 
    void A::operator += (const int& n) -> enable_if(type == TypeEnum::Type2) { // if not compile error 
     x = x + n; 
    } 
}; 
+0

最简单的将添加一个断言,等待运行时错误。否则,这种事情更多的是通过派生来完成。 –

+0

这将很容易使用不同的类和多态,但我想使用它与相同的名称(在这个例子中的A)和两个同名的类是不可能的。即使他们有不同的构造函数。 – Heinrich

+1

这已经是无效的C++。你有意在那里使用'新'吗? –

回答

2

您可以使用专业化:

enum struct TypeEnum : int { 
    TYPE_1 = 1, 
    TYPE_2 = 2 
}; 

template<TypeEnum Type> 
class A; 

template<> 
class A<TypeEnum::TYPE_1> 
{ 
public: 
    A(void) { } 
}; 

template<> 
class A<TypeEnum::TYPE_2> 
{ 
public: 
    A(int _x) { 
     x = _x; 
    } 
    int x; 
    void operator += (const int& n) { 
     x = x + n; 
    } 
}; 

int main() { 
    A<TypeEnum::TYPE_1> test1; 
    A<TypeEnum::TYPE_2> test2{1}; 

    test1 += 5; // compiler error should be here 
    test2 += 5; // OK 

    return 0; 
} 
+0

这是一个不错的解决方案。我会尝试。还有一种方法可以通过构造函数而不是模板来“分割”类吗? – Heinrich

+0

对于我的任务是这是最好的解决方案 – Heinrich

0

奇怪的是,你没有得到编译错误的位置:

// function only for Type 2 
void A::operator += (const int& n) { 
    x = x + n; 
} 

我想你想要的东西如:

// function only for Type 2 
A& operator += (int n) { 
    x = x + n; 
    return *this; 
} 

回答你的问题 - C++不能像这样工作。尽管如此,你可以实现类似的模板,但我建议不要这样做,除非它只是一个测试程序。

+0

这就是我想在这里返回x。这是一个错误。我试图把我的问题降到最低限度,不要发布1000行代码。 – Heinrich

+0

@ Heinrich认为'template class A;'然后你需要为1和2编写两个专门化。'template <> class A <1> {... with operator + = ...};'and'template <> A类<2> {...没有operator + =}的实现;'。结果A <1>将有+ =和A <2>将没有它。 – AlexT

+0

返回'void'没有什么不合法的,所以如果他得到编译错误会很奇怪。 –

1

也许下面可能会有帮助:

class A { 
public: 
    explicit A(TypeEnum type) : type(type) {} 
    virtual ~A() {} 
protected: 
    enum struct TypeEnum : int { 
     TYPE_1 = 1, 
     TYPE_2 = 2 
    }; 
    const TypeEnum type; 
}; 

class B : public A{ 
public: 
    B() : A(TYPE_1) {} 
}; 

class C : public A{ 
public: 
    explicit C(int x) : A(TYPE_2), x(x) {} 
    C& operator += (int n) { x = x + n; } 
private: 
    int x; 
}; 

继承在这里反映一个共同的类型你的情况。这不是必需的。

你反正可以做一件事:

B make_A() { return B{}; } 
C make_A(int x) { return C{x}; } 

int main() { 
    auto test1 = make_A(); // B 
    auto test2 = make_A(1); // C 

    test1 += 5; // compiler error should be here 
    test2 += 5; // OK 

    return 0; 
} 
+0

谢谢!这真的很好,但不是我的任务的解决方案。 – Heinrich