Спецификатор доступа по умолчанию для наследования
Если у меня есть, например, два класса A
и B
, такие что класс B
наследует A
следующим образом:
class B: public A
В этом случае я наследую public
.
Если я напишу предыдущий код следующим образом:
class B: A
Какой тип наследования я буду делать здесь (т.е. публичный)? Другими словами, что такое спецификатор доступа по умолчанию?
Просто побочный вопрос. Я вызываю предыдущую строку кодов statements
? Особенно, что я помню, я читал в С++ Without Fear: Руководство для начинающих, которое заставляет вас чувствовать себя умной книгой, которая statements
такова, что это конец с ;
. Что вы думаете об этом?
Спасибо.
Ответы
Ответ 1
Просто небольшое дополнение ко всем существующим ответам: тип наследования по умолчанию зависит от наследуемого (производного) типа (в данном примере B
), а не от того, который наследуется (базовый) (A
в пример).
Например:
class A {};
struct B: /* public */ A {};
struct A {};
class B: /* private */ A {};
Ответ 2
Он частный для класса и public для struct.
Ответ на сторону: Нет, это определения класса в соответствии со стандартом.
Ответ 3
Если вы используете class
для определения своего класса, спецификатор доступа по умолчанию будет private
. (Я тоже ошибаюсь.) Если вы используете struct
, это будет public
.
И определения классов - это декларации, я думаю. Утверждение - это то, что переводится в фактический код (если только не оптимизирован).
Однако, мягко экзотическая особенность C и С++ заключается в том, что выражения являются операторами. Вот почему 3+4;
является синтаксически юридическим утверждением в С++ (хотя многие компиляторы будут предупреждать об этом, не имея никакого эффекта). Хотя в этом случае это, очевидно, вздор, в целом выражения оцениваются для их побочных эффектов. (Очевидным примером является отказ от возвращаемого значения функции. Вы вызываете функцию не для получения результата, а для его побочных эффектов.)
Ответ 4
Когда вы наследуете класс из другого класса, спецификатор доступа по умолчанию является закрытым.
#include <stdio.h>
class Base {
public:
int x;
};
class Derived : Base { }; // is equilalent to class Derived : private Base {}
int main()
{
Derived d;
d.x = 20; // compiler error becuase inheritance is private
getchar();
return 0;
}
Когда вы наследуете структуру из другого класса, тогда спецификатор доступа по умолчанию является общедоступным.
#include < stdio.h >
class Base {
public:
int x;
};
struct Derived: Base {}; // is equilalent to struct Derived : public Base {}
int main() {
Derived d;
d.x = 20; // works fine becuase inheritance is public
getchar();
return 0;
}
Ответ 5
Если вы не выбрали наследование, С++ по умолчанию использует private
наследование так же, как члены класса по умолчанию имеют private
доступ для классов.
Ответ 6
Тип наследования по умолчанию частный в С++.
class B:A
{};
эквивалентно
class B: private A
{};
Ответ 7
"Тип" наследования зависит от того, как определяется класс. Для наследования применяются спецификаторы доступа по умолчанию. Из стандарта С++:
[class.access.base]/2
В отсутствие спецификатора доступа для базового класса public предполагается, когда производный класс определен с помощью ключа класса struct
и private принимается, когда класс определяется ключом класса class
. [Пример:
class B { /* ... */ };
class D1 : private B { /* ... */ };
class D2 : public B { /* ... */ };
class D3 : B { /* ... */ }; // B private by default
struct D4 : public B { /* ... */ };
struct D5 : private B { /* ... */ };
struct D6 : B { /* ... */ }; // B public by default
class D7 : protected B { /* ... */ };
struct D8 : protected B { /* ... */ };
Здесь B является публичной базой D2, D4 и D6, частной базой D1, D3, и D5, и защищенной базой D7 и D8. - конец примера]
Ответ 8
спецификатор доступа по умолчанию является важным отличием между классами и структурами. Он по умолчанию открыт для structs и private по умолчанию для классов.
Ответ 9
КАК другая проблема с литьем у вас есть
class A { virtual void test() = 0; };
class B : virtual public A { virtual void testb() {} };
class C : virtual public A { virtual void testc() {} };
class D : public B, public C {
virtual void test() override {}
}
void main() {
D d;
void* v = &d;
A* a = &d;
((D*)A)->test(); //OK
((D*)v)->test(); //undefined behavior (that call testb() in vtable logic at 1st inheritance position)
dynamic_cast<D*>(v)->test(); //compile error cast from void* not permitted
//resolution
void* x = a;
((D*)x)->test(); //OK but as you can see, you must to store a* in x*
}