C ++类派生和超级构造器混淆

时间:2010-05-12 17:55:04

标签: c++ oop

嘿,在教程C ++代码中,我发现了这个特殊的混乱:

PlasmaTutorial1::PlasmaTutorial1(QObject *parent, const QVariantList &args)
    : Plasma::Applet(parent, args), // <- Okay, Plasma = namespace, Applet = class
    m_svg(this),                    // <- A member function of class "Applet"?
    m_icon("document")              // <- ditto?
{
    m_svg.setImagePath("widgets/background");
    // this will get us the standard applet background, for free!
    setBackgroundHints(DefaultBackground);
    resize(200, 200);
}

我不是面向对象编程的新手,所以类派生和超类并不复杂,但这种语法让我感到困惑。

头文件定义了这样的类:

class PlasmaTutorial1 : public Plasma::Applet
{

与上面类似,命名空间Plasma和类Applet。但public做什么呢?

我担心我已经知道了这个概念,但是没有掌握C ++的语法/方法。

this问题中,我发现这些被称为“超级构造者”,至少这是我记忆中的问题,但我并没有完全理解这一点。

如果我们回头看第一个片段,我们会看到Constructor::Class(...) : NS::SuperClass(...),一切都很好'直到这里。但m_svg(this), m_icon("document")做什么呢?这是一种使派生类知道这些特定函数的方法吗?

这是C ++基础知识的一部分还是更直接?虽然我没有完全迷失在C ++中,但我在C中感觉更加自信:)

到目前为止,我所做的大部分OOP都是用D,Ruby或Python完成的。例如在D中,我只需定义class MyClass : MySuperClass,覆盖我需要的内容,并在需要时调用超类的构造函数。


好的,在阅读了一些答案后,是这个......

PlasmaTutorial1::PlasmaTutorial1(QObject *parent, const QVariantList &args)
    : Plasma::Applet(parent, args), // <- Call the _parent_ constructor
    m_svg(this),         // <- set m_svg  (in the _derived_ class) to "this"
    m_icon("document")   // <- set m_icon (in the _derived_ class) to "document"
{
    ...
}

...假设正确吗?


到目前为止,测试证实了我的假设。非常感谢!选择一个获胜的答案是一个艰难的选择,... ...

4 个答案:

答案 0 :(得分:3)

您所看到的是initialization list。它们受C++ FAQ Lite和加速成员初始化的鼓励,因为您的成员在进入构造函数之前不需要使用默认值。

答案 1 :(得分:2)

它们不是成员函数,它们是初始化列表。

基本上,这意味着

PlasmaTutorial1::PlasmaTutorial1(QObject *parent, const QVariantList &args)
    : Plasma::Applet(parent, args), // <- Call the parent constructor
    m_svg(this),                    // <- m_svg = this
    m_icon("document")              // <- m_icon = "document"
{
    m_svg.setImagePath("widgets/background");
    // this will get us the standard applet background, for free!
    setBackgroundHints(DefaultBackground);
    resize(200, 200);
}

此外,与某些面向对象语言不同,C ++在子类中具有“范围更改”的概念。基本上,继承语法中的public关键字意味着从基类继承的可公开访问的成员可以在派生类中公开访问。

使用private关键字继承的类同样会使超类中的所有可公开访问的成员成为子类中的私有。

答案 2 :(得分:2)

PlasmaTutorial1::PlasmaTutorial1(QObject *parent, const QVariantList &args)
    : Plasma::Applet(parent, args), // <- Okay, Plasma = namespace, Applet = class
    m_svg(this),                    // <- A member function of class "Applet"?
    m_icon("document")              // <- ditto?

这是一个初始化列表。您可以使用它来初始化成员和/或基类。考虑一个较小(但完整)的例子:

class base {
    int v;
public:
    base(int init) : v(val) {}
};

在这种情况下,v(val)部分是初始化列表。由于我们只是初始化一个int,它几乎相当于:

    base(int init) { v = init; }

如果您的成员为const,则会产生差异(例如)。必须初始化const变量,但不能分配。因此,(非静态)const成员强制您使用初始化列表:

class X { 
    int const a;
public:
    X(int init) : a(init) {}
};

如果您将引用作为类的成员,则会出现相同的情况。

  

class PlasmaTutorial1:public Plasma :: Applet

     

与上面类似,命名空间Plasma和类Applet。但公众在那里做什么呢?

公众只是指定公共继承,因此基类中的公共内容在派生类中仍然是公共的。您还可以指定私有继承,在这种情况下,从父级继承的所有内容在派生类中都将变为私有。此外,对于私有继承,没有从派生到基础的隐式转换。

您通常认为从设计角度继承的任何内容通常都是在C ++实现中建模为公共继承。私有继承通常只是用于实现(附加的通常含义是“以”来实现,而不是“A”)。

答案 3 :(得分:1)

public表示父公共类成员也将是派生类的公共类成员。

您在构造函数的初始化列表中看到的成员是派生类(m_svg,m_icon)的成员。您无法初始化父级成员。