Вывод класса C ++ и путаница в суперконструкторе - PullRequest
0 голосов
/ 12 мая 2010

Эй, в учебном коде на 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? 1010 *

Боюсь, что я уже знаю эту концепцию, но не понимаю синтаксиса C ++ / способа сделать это.

В этом вопросе я поднял вопрос о том, что они называются «суперконструкторами», по крайней мере, это то, что застряло в моей памяти, но я не понимаю этого в полной мере.

Если мы оглянемся назад на первый фрагмент, мы увидим Constructor::Class(...) : NS::SuperClass(...), все в порядке 'до здесь. Но что m_svg(this), m_icon("document") делает там? Это какой-то метод, позволяющий сделать эти конкретные функции известными производному классу?

Является ли это частью основ C ++ или более непосредственным? Хотя я не совсем потерян в C ++, я чувствую себя намного лучше в C:)

Большая часть ООП, которую я сделал до сих пор, была сделана на 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 ]

3 голосов
/ 12 мая 2010

Вы видите список инициализации . Они поощряются C ++ FAQ Lite и ускоряют инициализацию членов, потому что ваши члены не должны принимать значения по умолчанию перед входом в конструктор.

2 голосов
/ 12 мая 2010
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) {}
};

Такая же ситуация возникает, если у вас есть ссылка в качестве члена класса.

класс PlasmaTutorial1: общедоступная плазма :: Апплет

Аналогично выше, пространство имен Plasma и класс Applet. Но что там делает публика?

Public просто указывает публичное наследование, поэтому то, что public в базовом классе, остается открытым в производном классе. Вы также можете указать частное наследование, в этом случае все наследуемое от родителя становится частным в производном классе. Кроме того, при частном наследовании нет неявного преобразования из производного в базовое.

Все, что вы обычно рассматриваете как наследование с точки зрения проектирования, обычно моделируется как публичное наследование в реализации C ++. Частное наследование, как правило, предназначено только для реализации (обычно добавляется значение «реализовано в терминах», а не «является А»).

2 голосов
/ 12 мая 2010

Они не являются функциями-членами, это списки инициализации.

В основном это означает

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, аналогичным образом сделает все общедоступные члены в суперклассе private в подклассе.

1 голос
/ 12 мая 2010

public означает, что члены открытого класса родителя также будут членами открытого класса производного класса.

Члены, которые вы видите в списке инициализации конструктора, являются членами производного класса (m_svg, m_icon). Вы не можете инициализировать членов родителя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...