2015-10-31 3 views
0

В приведенном ниже коде класс B имеет член, который имеет тип класса A (varA1). Я хочу, чтобы создать объект класса B, где элемент varA1 предназначен для использования конструктора не по умолчанию (интермедиат v1) в классе А.C++ Default Constructor Called

#include <iostream> 
using std::cout; using std::endl; using std::string; 

class A { 
public: 
    A() { cout << "A default constructor" << endl;} 
    A(int v1); 
private: 
    int var1; 
}; 
A::A(int v1) { 
    cout << "A int constructor" << endl; 
    var1 = v1; 
} 

class B { 
public: 
    B() { cout << "B default constructor" << endl;} 
    B(int v1); 
private: 
    int var1; 
    A varA1; 
}; 
B::B(int v1) { 
    cout << "B int constructor" << endl; 
    var1 = v1; 
    A varA1(int v1); 
} 

int main() 
{ 
    A TestA(1); 
    B TestB(1); 

    return 0; 
} 

Однако, когда я запускаю код, приведенный выше, я получаю следующий результат:

A int constructor 
A default constructor 
B int constructor 

Должно быть, я ошибаюсь. Что мне нужно изменить, чтобы класс B использовал конструктор A (int v1) не по умолчанию в классе A?

Я использую ubuntu 14.04LTS. Аналогичные результаты получили как GNU G ++ 4.9, так и 5.1.

Заранее благодарим за чтение и ответ.

ответ

3

Используйте member initialization list:

B::B(int v1) : var1(v1), varA1(v1) { 
    cout << "B int constructor" << endl; 
} 

Обратите внимание, что члены инициализируются (построены) в том же порядке, что они объявлены в классе, так что переключение заказов в списке инициализации членов не изменит порядок в котором происходит строительство (и, надеюсь, ваш компилятор предупредит вас об этом). Эта небольшая деталь становится важной, если вы попытаетесь построить varA1 от var1 и var1 объявлено после varA1 в определении класса.


И, кстати, все это делает линия (внутри B::B(int v1) конструктора):

A varA1(int v1); 

поступательно объявить функцию с именем varA1, который принимает int параметр и возвращает объект A. Это полуподобно с most vexing parse, хотя на самом деле это не самый неприятный синтаксический анализ.

+0

Это работает. Является ли список инициализации членов единственным способом для этого? Спасибо за дополнительную информацию! – user3569894

+0

@ user3569894: В значительной степени. C++ 11 добавил более удобную [инициализацию члена] (http://stackoverflow.com/questions/13662441/c11-allows-in-class-initialization-of-non-static-and-non-const-members-what- c), а также добавлена ​​[агрегатная инициализация] (http://en.cppreference.com/w/cpp/language/aggregate_initialization). Эти новые функции полезны, но они не позволяют избежать использования списка инициализации членов в этой ситуации. – Cornstalks

+0

Еще раз благодарю вас за быстрый ответ и благодарность Джеймсону. – user3569894

1

Вы можете использовать список инициализации в вашем B :: B (INT) конструктор:

B::B(int v1) : varA1(v1) { 
    cout << "B int constructor" << endl; 
    var1 = v1; 
} 
0

Если вы не хотите, CTOR по умолчанию, вы можете использовать

A(void) = delete; 

Но признают, что вы можете временно добавить это объявление в качестве диагностической меры, чтобы заставить компилятор сообщить вам, для какого кода он хочет использовать значение по умолчанию ctor.

Заменяя

A() { std::cout << "A default constructor" << std::endl;} 

с

A() = delete; 

Компилятор будет жаловаться на использование удаленной функции 'A :: A()' в теле B :: B (интермедиат v1).

Таким образом, краткий осмотр идентифицирует, что второй атрибут данных B, то есть «B :: varA1», использует по умолчанию ctor A (теперь удален).

Вы также можете подумать о том, что «исправление» B ctor НЕ используется по умолчанию ctor A, явно вызывая «varA1 (0)» в списке инициализаторов B ctor.

+0

Я думаю, что использование синтаксиса C-стиля 'A (void)' немного странно. Но в целом я думаю, что вы хорошо знаете об удалении конструкторов, которые не предназначены для использования. – Cornstalks

+0

@Cornstalks - From [Стандарт C++, 8.3.5/2: Если предложение parameter-declaration пусто, функция не принимает аргументов. Список параметров (void) эквивалентен списку пустых параметров. ] Это ответ 2009 года в SO, и это то, чему меня учили (ммм, некоторое время назад). Я считаю это явным (то есть он показывает читателям моего кода, что я намеренно не хотел никаких параметров, и не просто упускал из вида проблему). Я не считаю это C-style ... но я признаю, что знаю минимальное C. –

+0

Я знаю, что это действительно C++. Но это было [унаследовано от C] (http://stackoverflow.com/q/51032/1287251), поэтому я указываю это. В C++ функция 'A()' явно показывает, что функция не принимает никаких параметров (и она интуитивно понятна: нет параметров, поэтому нет параметров) (и это явно преднамеренно: если вы хотите какие-либо параметры, вы получите ошибка компилятора, если вы пытались передать или использовать какой-либо). У вас есть действующие личные предпочтения, но я хотел добавить примечание об этом, поскольку OP (явно) новый для C++, и я хотел помочь им избежать ненужного использования привычек C. – Cornstalks

Смежные вопросы