【问题标题】:Forbid using default constructor in derived classes, C++禁止在派生类中使用默认构造函数,C++
【发布时间】:2015-10-30 00:39:45
【问题描述】:

有没有办法创建基类(例如boost::noncopyable)并从它继承,如果它不是由用户(开发者)?

例子:

class SuperDad {
XXX:
  SuperDad(); // = delete?
};

class Child : YYY SuperDad {
public:
  Child(int a) {...}
};

结果:

int main () {
  Child a;     // compile error
  Child b[7];  // compile error
  Child c(13); // OK
}

【问题讨论】:

  • 将其设为私有。看到这个问题stackoverflow.com/questions/10474417/…
  • 确实有效。万分感谢!要使其正常工作,很难理解继承级别和修饰符组合。
  • 已编辑:这是对先前消失的评论的回答。
  • @RAEC,这种方式将完全弃用继承,请参阅this topic
  • 他仍然可以用一个参数声明他的构造函数并将其公开,顺便说一句,在 C++11 中你实际上可以“删除”构造函数en.cppreference.com/w/cpp/language/default_constructorClassName() = delete ;

标签: c++ inheritance constructor default-constructor


【解决方案1】:

将构造函数设为私有。

protected:
    Base() = default;

【讨论】:

  • 好的,谢谢。回答“将其设为私有”一开始并不完全清楚(@RAEC),因为 private 修饰符做了很多其他事情。
  • 根据Tomasz Sodzawiczny 的公平评论,如果我们使用这种方法,上面示例中的代码将编译,直到用户为 Child 定义了自己的非平凡构造函数。
【解决方案2】:
#include <iostream>
using namespace std;


class InterfaceA
{
public:

InterfaceA(std::string message)
{
    std::cout << "Message from InterfaceA: " << message << std::endl;
}

private:
    InterfaceA() = delete;
};


class MyClass: InterfaceA
{
public:
    MyClass(std::string msg) : InterfaceA(msg)
    {
        std::cout << "Message from MyClass: " << msg << std::endl;
    }
};

int main()
{
    MyClass c("Hello Stack Overflow");
    return 0;
}

【讨论】:

  • 可以,但是你应该在基类中声明带有参数的公共构造函数。以前的答案更优雅,更紧凑,不是吗? :) 此外,通过这种方法,您可以创建 InterfaceA 对象,这可能是有问题的。
  • 他特别说他想“禁止在派生类中使用默认构造函数,C++”大声笑将默认值设置为已经默认的构造函数对那个没有帮助。在上一个答案中,他仍然可以继承它并使用默认构造函数。但是有各种各样的答案很好,他只是获得了比他想象的更多的知识哈哈
  • 是的,当然,这很好,谢谢你(我已经“+”你的回答),这是我的问题:)
  • 哦,哇,我才意识到你是提出这个问题的人,天哪,抱歉,我之前可能会为你提供代码和更好的答案,但我认为是其他人在讨论这个和我一起:/对不起;希望这一切对你有所帮助哈哈
【解决方案3】:

根据this cppreference.com article(基本上是C++标准12.1.部分的律师到人的翻译):

如果没有为类提供任何类型的用户定义构造函数 类型(结构、类或联合),编译器将始终声明一个 默认构造函数作为其类的内联公共成员。

您可以从SuperDad 控制隐式定义的Child 构造函数的唯一方法是让编译器将其定义为deleted

您可以通过使SuperDad 的默认构造函数(或析构函数)被删除、模棱两可或不可访问来做到这一点——但是您必须定义一些其他方式来创建基类并从所有子构造函数中隐式使用它。

【讨论】:

  • 它将一直编译,直到用户定义了自己的 Child 非平凡构造函数(带参数)。因此,在这种情况下,Ben 的回答在我的主题问题的上下文中是正确的。如果我想控制创建 Child's,我应该了解它们的使用案例并根据必要的逻辑定义至少一个非平凡的构造函数。
  • 据我了解,Ben 的回答只改变了基类的行为(不能直接实例化),而没有改变派生类的任何事情。
  • 重点是防止用户默认构造 Child(实际上,Child 类是一种 API)和错误用法,因此将基本构造函数设为私有确实会影响 Child 的行为。当然,我的问题可能有多种解释,因为我表述得不够准确。
猜你喜欢
  • 2019-02-07
  • 1970-01-01
  • 2011-12-25
  • 2014-12-19
  • 2012-11-24
  • 1970-01-01
  • 1970-01-01
  • 2016-12-16
  • 1970-01-01
相关资源
最近更新 更多