Вызов объявленного псевдонимом конструктора базового класса в другом пространстве имен

Я пытаюсь понять некоторые детали объявленных псевдонимами классов через 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) генерирует две ошибки для этого кода, которые я считаю связанными (хотя я не понимаю, как …)

Ошибка 1

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 в моем примере) в контексте введения имен классов. Любые указатели очень ценятся 🙂

Ошибка 2

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 и спасибо всем за огромную помощь, которую вы уже оказали мне, помогая другим с их проблемами!

1

Решение

Когда вы наследуете от класса, производный класс может обращаться к именам базового класса (включая само имя базового класса) без квалификации. Вы эффективно наследуете имена в базовом классе. Вот почему наследование от N::BarInt позволяет ссылаться на BarInt в A без квалификации.

За Bвы наследуете от Foo<double> используя псевдоним BarFloat, но Foo<double> не содержит BarFloatтак что вы не наследуете это имя.

Вторая ошибка только из-за первого сбоя. Поскольку компилятор не видел допустимой инициализации базы, это похоже на то, что вы вообще не инициализировали базу явно, поэтому он вынужден инициализировать ее конструктором по умолчанию, которого у вас нет.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]