Пример кода приведен внизу сообщения. Меня озадачивает спецификатор защищенного доступа в классе. Я определил узел класса, который имеет защищенное строковое имя члена
Имя строки;
И вектор указателей узлов
Векторные аргументы;
Раньше я думал, что функция-член узла не может
Args [0] -> имя
Но программа, которая делает именно это, компилируется и запускается. Однако теперь я хотел бы унаследовать этот класс и получить доступ к полю имени в одном из указателей массива args из этого производного класса.
Args [0] -> имя
Но это не компилируется. Когда я компилирую приведенный ниже пример кода с раскомментированными разделами с комментариями, компилятор сообщает:
Выход компилятора:
G ++ test.cc -o тест
Test.cc: в функции-члене void foo :: newnode :: print_args2 ():
Test.cc:22: ошибка: 'std :: string foo :: node :: name' защищен
Test.cc:61: ошибка: в этом контексте
Компиляция завершилась ненормально с кодом 1 в четверг, 17 июня, 12:40:12
Вопросов:
Почему я могу получить доступ к полю имени указателей узлов в аргументах в class node, потому что это то, что я ожидал бы от аналогичного определенное частное поле в Java.
Как мне получить доступ к этим полям из производного класса.
Пример кода:
#include <iostream>
#include <vector>
using namespace std;
namespace foo
{
class node;
typedef std::vector<node*> nodes;
class node
{
public:
node (string _name);
void print_args ();
void add_node (node* a);
protected:
nodes args;
string name;
};
}
foo::node::node (string _name)
: args(0)
{
name = _name;
}
void foo::node::add_node (node* a)
{
args.push_back(a);
}
void foo::node::print_args ()
{
for (int i = 0; i < args.size(); i++)
{
cout << "node " << i << ": " << args[i]->name << endl;
}
}
// namespace foo
// {
// class newnode : public node
// {
// public:
// newnode (string _name) : node(_name) {}
// void print_args2 ();
// protected:
// };
// }
// void foo::newnode::print_args2 ()
// {
// for (int i = 0; i < args.size(); i++)
// {
// cout << "node " << i << ": " << args[i]->name << endl;
// }
// }
int main (int argc, char** argv)
{
foo::node a ("a");
foo::node b ("b");
foo::node c ("c");
a.add_node (&b);
a.add_node (&c);
a.print_args ();
// foo::newnode newa ("newa");
// foo::newnode newb ("newb");
// foo::newnode newc ("newc");
// newa.add_node (&newb);
// newa.add_node (&newc);
// newa.print_args2 ();
return 0;
}
2 ответа
Компилятор разрешит объекту A
получить доступ к закрытым / защищенным членам объекта B
, если A
и B
имеют один и тот же статический тип.
Я постараюсь пояснить это на примере:
class Base
{
protected:
int a;
};
class Derived : public Base
{
public:
void foo(Base& b, Derived& d)
{
//allowed because this obviously has the same type as this :)
a = 1;
//allowed because this has the same type as d (Derived)
d.a = 1;
//not allowed because this (Derived) does not have the same
//type as b (Base). They might have the same dynamic type
//but the compiler has no way of knowing this.
b.a = 1;
}
};
Итак, чтобы ответить на ваши вопросы:
- Классу
node
разрешен доступ к полюname
, если указателиnode
вашего вектораargs
, потому что они также относятся к классуnode
. - Вы не можете напрямую. Вы должны либо сделать поле общедоступным (я бы этого не сделал), либо сделать общедоступные методы доступа.
b
, в Derived
, вы сможете сделать d.b = 1
в приведенном выше фрагменте.
Хм .. Попробую объяснить :)
Проблема заключается в способе доступа к переменной name : через объект node , а не из класса newnode , как вы ожидали. Возможное решение - добавить метод получения для переменной name :
cout << "node " << i << ": " << args[i]->GetName() << endl;
GetName () должен быть помещен в класс node и может выглядеть следующим образом:
std::string GetName() const
{
return name;
}
Похожие вопросы
Новые вопросы
c++
C++ — это язык программирования общего назначения. Изначально он разрабатывался как расширение C и имел аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде, который будет скомпилирован с помощью компилятора C++. Используйте тег версии для вопросов, связанных с конкретной стандартной версией [C++11], [C++14], [C++17], [C++20] или [C++23]. и т.д.