Example code is included at the bottom of the message. I'm puzzled about the protected access specifier in a class. I have define a class node which has a protected string member name
string name;
and a vector of node pointers
vector args;
Before I thought that a member function of node could not do
args[0]->name
but a program that does just this does compile and run. However, now I would like to inherit this class and access the name field in one of the args array pointers from this derived class
args[0]->name
but this does not compile. When I compile the example code below with the commented sections uncommented, the compiler reports:
Compiler output:
g++ test.cc -o test
test.cc: In member function 'void foo::newnode::print_args2()':
test.cc:22: error: 'std::string foo::node::name' is protected
test.cc:61: error: within this context
Compilation exited abnormally with code 1 at Thu Jun 17 12:40:12
Questions:
Why can I access the name field of the node pointers in args in class node, because this is what I would excpect from a similarly defined private field in Java.
How can I access those fields from the derived class.
Example code:
#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
开发者_StackOverflow// {
// 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;
}
The compiler will allow that an object A
accesses private/protected members of an object B
if A
and B
have the same static type.
I will try to make this clear with an example:
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;
}
};
So, to answer your questions:
- Class
node
is allowed to access thename
field if thenode
pointers of yourargs
vector because they are also of classnode
. - You cannot directly. You either have to make the field public (I wouldn't do that) or make public accessors.
Hm.. I'll try to explain:)
The problem is in the way you're accessing the name variable: trough the node object and not from the newnode class as you expecting. Possible solution would be that you add an getter method for the name variable:
cout << "node " << i << ": " << args[i]->GetName() << endl;
GetName() should be placed in the node class and can look like following:
std::string GetName() const
{
return name;
}
精彩评论