102

メンバー変数としていくつかのオブジェクトを持つクラスがあります。宣言時にこれらのメンバーのコンストラクターを呼び出したくないので、オブジェクトへのポインターを明示的に保持しようとしています。何をしているかが自分もわからない。

オブジェクトメンバー変数を初期化するときにコンストラクターがすぐに呼び出される場合、次のことができるのではないかと思いました。

class MyClass {
    public:
        MyClass(int n);
    private:
        AnotherClass another(100); // Construct AnotherClass right away!
};

MyClassしかし、コンストラクターにコンストラクターを呼び出してもらいたいですAnotherClass。私のコードは次のようになります。

ファイルBigMommaClass.h

#include "ThingOne.h"
#include "ThingTwo.h"

class BigMommaClass {

        public:
                BigMommaClass(int numba1, int numba2);

        private:
                ThingOne* ThingOne;
                ThingTwo* ThingTwo;
};

ファイルBigMommaClass.cpp

#include "BigMommaClass.h"

BigMommaClass::BigMommaClass(int numba1, int numba2) {
        this->ThingOne = ThingOne(100);
        this->ThingTwo = ThingTwo(numba1, numba2);
}

コンパイルしようとすると、次のエラーが表示されます。

g++ -Wall -c -Iclasses -o objects/BigMommaClass.o classes/BigMommaClass.cpp
In file included from classes/BigMommaClass.cpp:1:0:
classes/BigMommaClass.h:12:8: error: declaration of âThingTwo* BigMommaClass::ThingTwoâ
classes/ThingTwo.h:1:11: error: changes meaning of âThingTwoâ from âclass ThingTwoâ
classes/BigMommaClass.cpp: In constructor âBigMommaClass::BigMommaClass(int, int)â:
classes/BigMommaClass.cpp:4:30: error: cannot convert âThingOneâ to âThingOne*â in assignment
classes/BigMommaClass.cpp:5:37: error: â((BigMommaClass*)this)->BigMommaClass::ThingTwoâ cannot be used as a function
make: *** [BigMommaClass.o] Error 1

正しいアプローチを使用していますが、構文が間違っていますか? それとも、別の方向からこれに来る必要がありますか?

4

5 に答える 5

110

メンバー初期化子リストでメンバーを初期化する方法を指定できます。

BigMommaClass {
    BigMommaClass(int, int);

private:
    ThingOne thingOne;
    ThingTwo thingTwo;
};

BigMommaClass::BigMommaClass(int numba1, int numba2)
    : thingOne(numba1 + numba2), thingTwo(numba1, numba2) {}
于 2012-10-17T04:39:09.563 に答える
38

ThingOnewhichを使用してを作成しようとしていますが、動作しoperator=ません (構文が正しくありません)。また、クラス名を変数名として使用しています。つまり、ThingOne* ThingOne. まず、変数名を修正しましょう。

private:
    ThingOne* t1;
    ThingTwo* t2;

これらはポインターであるため、何かを指している必要があります。オブジェクトがまだ構築されていない場合は、コンストラクターで new を使用して明示的にBigMommaClass構築する必要があります。

BigMommaClass::BigMommaClass(int n1, int n2)
{
    t1 = new ThingOne(100);
    t2 = new ThingTwo(n1, n2);
}

ただし、一般的には初期化子リストが構築に適しているため、次のようになります。

BigMommaClass::BigMommaClass(int n1, int n2)
    : t1(new ThingOne(100)), t2(new ThingTwo(n1, n2))
{ }
于 2012-10-17T04:39:57.510 に答える
12

この質問は少し古いですが、メンバー変数を初期化する前にコンストラクターで「より多くの作業を行う」C++ 11 の別の方法を次に示します。

BigMommaClass::BigMommaClass(int numba1, int numba2)
    : thingOne([](int n1, int n2){return n1+n2;}(numba1,numba2)),
      thingTwo(numba1, numba2) {}

上記のラムダ関数が呼び出され、結果が thingOnes コンストラクターに渡されます。もちろん、ラムダを好きなだけ複雑にすることもできます。

于 2015-12-03T23:28:43.523 に答える
3

クラスメンバーが「真の複合」メンバーとして(つまり、ポインター参照としてではなく)保持されている状況に対する解決策を提案したクリスからの最初の(そして素晴らしい)回答について:

メモは少し大きいので、ここでサンプル コードを使用して説明します。

前述のようにメンバーを保持することを選択した場合、次の 2 つの点にも留意する必要があります。

  1. デフォルトのコンストラクターを持たないすべての「構成されたオブジェクト」について、「親」クラスのすべてのコンストラクターの初期化リストで初期化する必要があります (つまり、元の例と以下のコードで)。いくつかあります (以下の例を参照)。つまり、デフォルトのコンストラクターを有効にした場合にのみ、 andを「コメント化」できます。BigMommaClassMyClassMyClassInnerClass1m_innerClass1(a)m_innerClass1(15) InnerClass1

  2. デフォルトのコンストラクターを持つすべての「構成されたオブジェクト」については、初期化リスト内で初期化できますが、そうしないことを選択した場合も機能します (以下InnerClass2の例を参照)。

サンプル コードを参照してください (バージョン 7.3.0のUbuntu 18.04 (Bionic Beaver) でコンパイル):g++

#include <iostream>

using namespace std;

class InnerClass1
{
    public:
        InnerClass1(int a) : m_a(a)
        {
            cout << "InnerClass1::InnerClass1 - set m_a:" << m_a << endl;
        }

        /* No default constructor
        InnerClass1() : m_a(15)
        {
            cout << "InnerClass1::InnerClass1() - set m_a:" << m_a << endl;
        }
        */

        ~InnerClass1()
        {
            cout << "InnerClass1::~InnerClass1" << endl;
        }

    private:
        int m_a;
};

class InnerClass2
{
    public:
        InnerClass2(int a) : m_a(a)
        {
            cout << "InnerClass2::InnerClass2 - set m_a:" << m_a << endl;
        }

        InnerClass2() : m_a(15)
        {
            cout << "InnerClass2::InnerClass2() - set m_a:" << m_a << endl;
        }

        ~InnerClass2()
        {
            cout << "InnerClass2::~InnerClass2" << endl;
        }

    private:
        int m_a;
};

class MyClass
{
    public:
        MyClass(int a, int b) : m_innerClass1(a), /* m_innerClass2(a),*/ m_b(b)
        {
            cout << "MyClass::MyClass(int b) - set m_b to:" << m_b << endl;
        }

         MyClass() : m_innerClass1(15), /*m_innerClass2(15),*/ m_b(17)
        {
            cout << "MyClass::MyClass() - m_b:" << m_b << endl;
        }

        ~MyClass()
        {
            cout << "MyClass::~MyClass" << endl;
        }

    private:
        InnerClass1 m_innerClass1;
        InnerClass2 m_innerClass2;
        int m_b;
};

int main(int argc, char** argv)
{
    cout << "main - start" << endl;

    MyClass obj;

    cout << "main - end" << endl;
    return 0;
}
于 2018-12-20T16:55:58.910 に答える