有没有一种方法可以禁止派生类中的基类方法调用?

时间:2019-09-20 19:09:23

标签: c++ oop

在c ++中,“保护”修饰符仅允许在派生类中进行方法调用。是否有可能实现逆逻辑-禁止在派生类中调用基类方法?下面的代码说明了我想要得到的。

class Base
{
   int data;
protected:
   // This constructor should be called only in the derived classes
   Base(int d): data(d) { }
public:
   // This construcor can be called wherever except a derived classes!
   Base(): data(0) { }
};

class Derived : public Base
{
public:
   // The developer must not forget to initialize "data"
   Derived() : Base(10) {}

   // I want to get a compilation error there
   Derived() : Base() {}
};

4 个答案:

答案 0 :(得分:2)

  

是否可以禁止在派生类中调用基类方法?

是的。通过使用专用访问说明符。私有名称只能由该类本身访问。

这不是反逻辑。不可能减少派生类对公共名称的可访问性。

答案 1 :(得分:2)

// This construcor can be called wherever except a derived classes!

没有办法做到这一点。公共函数可以被任何人调用,并且如果派生类调用该函数,则没有SFINAE技巧可以停止它,因为构造函数不知道从何处调用它。

答案 2 :(得分:1)

这似乎是XY问题。尽管我不建议这样做(我建议重新考虑设计),但我还是发现了(无论好坏)受CRTP模式启发的解决方案:

template <class D = void>
class Base
{    
protected:

    int data;

protected:
    // This constructor should be called only in the derived classes
    template <class Der = D, class = std::enable_if_t<std::is_base_of_v<Base, Der>>>
    Base(int d): data(d) {}

public:
    // This constructor can be called wherever except a derived classes!
    template <class Der = D, class = std::enable_if_t<!std::is_base_of_v<Base, Der>>>
    Base(): data(0) { }
};

class Derived : public Base<Derived>
{
    int mydata = 1;
public:
    // The developer must not forget to initialize "data"
    Derived() : Base(24) {}

    // I want to get a compilation error there
    //Derived() : Base() {} // (1) compilation error here
};
auto test()
{
    Base b1{};
    //Base b2{24}; // (2) compilation error here

    Derived d{};
}

当然有这个问题。对于初学者来说,创建派生类为class Derived : public Base<void>并没有阻止。

如果需要,您可以添加一个通用的基类

class Base_l0
{
};

template <class D = void>
class Base_l1 : Base_l0
{
};

class Derived : public Base_l1<Derived>
{
};

答案 3 :(得分:0)

简短的回答是“否”。

在C ++中,只有public protectedprivate。没有回旋的余地。您可以从任何地方(public),从类本身(private)之外的任何地方或从类及其子级(protected)来访问函数。

  

我只想强迫用户在继承[sic]之前执行一些其他操作。例如,为避免随机错误。

如果调用默认构造函数会在从其继承的同时调用它而导致错误,那么很可能在您从其继承时导致错误。这意味着您可能根本不应该将此构造函数公开,

相关问题