Я пытаюсь понять некоторые детали объявленных псевдонимами классов через C ++ 11 using
и как / почему это влияет на вызов конструктора базового класса.
#include <iostream>
namespace N {
template<typename T>
struct Foo
{
// Foo(){}; // NOTE: If this line is present, error 2 goes away.
Foo(T t):value(t){};
~Foo() = default;
T value;
};
struct BarInt : public Foo<int>
{
BarInt(int t):Foo< int >(t){};
~BarInt() = default;
};
using BarFloat = Foo<float>;
};
struct A : public N::BarInt
{
A(int i=42):BarInt(i){}; //BarInt(i) or N::BarInt(i) doesn't matter here
~A() = default;
};
struct B : public N::BarFloat
{
B(float f=23.0):BarFloat(f){}; //two errors with gcc4.7.2 (with -std=gnu++11)
// B(float f=23.1):N::BarFloat(f){}; //this line seems to work.
~B() = default;
};int main(int argc, char **argv)
{
A a;
B b;
std::cout << "a's value is "<< a.value << "\n"<< "b's value is "<< b.value << std::endl;
return 0;
}
gcc 4.7.2 (компиляция с -std = gnu ++ 11) генерирует две ошибки для этого кода, которые я считаю связанными (хотя я не понимаю, как …)
main.cpp: In constructor ‘B::B(float)’:
main.cpp:32:19: error: class ‘B’ does not have any field named ‘BarFloat’
Мои поиски на stackoverflow подняты Требуется ли пространство имен при обращении к базовому классу, который упоминает введенное имя класса в качестве отправной точки для дальнейшего поиска. Однако из того, что я собрал, это объясняет, почему я могу написать конструктор для A
как я это сделал (то есть как A(int i=42):BarInt(i){};
) и почему BarInt(i)
не должен быть квалифицирован с пространством имен N
,
Так почему же это не работает с B
? В соответствии с В чем разница между typedef и using в C ++ 11?, using
такой же, как старый добрый typedef
, так что я думаю, мой вопрос для первой ошибки, как класс, объявленный псевдонимом (BarFloat
в моем примере) отличаются от обычных занятий (BarInt
в моем примере) в контексте введения имен классов. Любые указатели очень ценятся 🙂
main.cpp:32:29: error: no matching function for call to ‘N::Foo<double>::Foo()’
main.cpp:32:29: note: candidates are:
main.cpp:9:5: note: N::Foo<T>::Foo(T) [with T = double]
main.cpp:9:5: note: candidate expects 1 argument, 0 provided
main.cpp:6:10: note: constexpr N::Foo<double>::Foo(const N::Foo<double>&)
main.cpp:6:10: note: candidate expects 1 argument, 0 provided
Эта ошибка исчезнет, если я, как уже отмечалось в приведенном выше примере кода, введу пустой Foo()
конструктор. У меня, однако, вопрос, почему BarFloat(f)
запускает вызов в пустую Foo()
конструктор и, в этом случае, как BarFloat.value
возможно будет установлен на 23,0.
Поскольку это мой первый пост здесь: Здравствуйте, stackoverflow и спасибо всем за огромную помощь, которую вы уже оказали мне, помогая другим с их проблемами!
Когда вы наследуете от класса, производный класс может обращаться к именам базового класса (включая само имя базового класса) без квалификации. Вы эффективно наследуете имена в базовом классе. Вот почему наследование от N::BarInt
позволяет ссылаться на BarInt
в A
без квалификации.
За B
вы наследуете от Foo<double>
используя псевдоним BarFloat, но Foo<double>
не содержит BarFloat
так что вы не наследуете это имя.
Вторая ошибка только из-за первого сбоя. Поскольку компилятор не видел допустимой инициализации базы, это похоже на то, что вы вообще не инициализировали базу явно, поэтому он вынужден инициализировать ее конструктором по умолчанию, которого у вас нет.
Других решений пока нет …