开发者

C++ class derivation and superconstructor confusion

Hey, in a tutorial C++ code, I found this particular piece of confusion:

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);
}

I'm not new to object oriented programming, so class derivation and super-classes are nothing complicated, but this syntax here got me confused.

The header file defines the class like this:

class PlasmaTutorial1 : public Plasma::Applet
{

Similar to above, namespace Plasma and class Applet. But what's the public doing there?

I fear that I already know the concept but don't grasp the C++ syntax/way of doing it.

In this question I picked up that these are called "superconstructors", at least that's what stuck in my memory, but I don't get this to the full extend.

If we glance back at the first snippet, we see Constructor::Class(...) : NS::Super开发者_如何学PythonClass(...), all fine 'till here. But what are m_svg(this), m_icon("document") doing there? Is this some kind of method to make these particular functions known to the derivated class?

Is this part of C++ basics or more immediate? While I'm not completly lost in C++, I feel much more at home in C :)

Most of the OOP I have done so far was done in D, Ruby or Python. For example in D I would just define class MyClass : MySuperClass, override what I needed to and call the super class' constructor if I'd need to.


Okay, after reading some of the answers, is this...

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"
{
    ...
}

...assumption correct?


Test's confirm my assumption so far. Thanks a lot! Picking a winning answer is a hard choice, tho...


What you are seeing is a initialization list. They are encouraged by the C++ FAQ Lite and speed up member initialization, because your members don't need to take default values before entering the constructor.


They are not member functions, they are intialization lists.

Basically, it means

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);
}

Also, unlike some object-oriented languages, C++ has the concept of "scope alteration" in sub-classing. Basically, The public keyword in the inheritance syntax means that publicly accessible members inherited from the base class stay publicly accessible in the derived class.

A class that is inherited with the private keyword will similarly make all publicly accessible members in the super-class private in the subclass.


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?

This is an initialization list. You can use it to initialize members and/or base classes. Consider a smaller (but complete) example:

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

In this case, the v(val) part is the initialization list. Since we're just initializing an int, it's pretty much equivalent to:

    base(int init) { v = init; }

The difference arises (for one example) if you have a member that's const. A const variable must be initialized, but cannot be assigned to. Therefore, a (non-static) const member forces you to use an initializer list:

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

The same situation arises if you have a reference as a member of a class.

class PlasmaTutorial1 : public Plasma::Applet

Similar to above, namespace Plasma and class Applet. But what's the public doing there?

The public is simply specifying public inheritance, so what's public in the base class remains public in the derived class. You can also specify private inheritance, in which case everything inherited from the parent becomes private in the derived class. In addition, with private inheritance there's no implicit conversion from derived to base.

Anything you'd normally think of as inheritance from a design perspective is normally modeled as public inheritance in a C++ implementation. Private inheritance is normally just for implementation (the usual meaning attached is "is implemented in terms of", not "is A").


public means the parent's public class members will also be public class members of the derived class.

The members you see in the initialization list of the constructor are members of the derived class (m_svg, m_icon). You can't initialize members of a parent.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜