static member functions access to class members and methods

R

Roger Leigh

The C++ book I have to hand (Liberty and Horvath, Teach yourself C++
for Linux in 21 Days--I know there are better) states that "static
member functions cannot access any non-static member variables".
However, this doesn't seem entirely correct. It also doesn't mention
whether static member functions can access protected and private
member data and methods (and I couldn't spot this in the FAQ).

I have a class row<Row> which derives from row_base:

template<typename Row>
class row : public row_base
{
public:
typedef std::auto_ptr<Row> row_ptr;

row(): row_base() {}

row(row_state status, bool modified=false):
row_base(status, modified) {}

virtual ~row() {}

static row_ptr create(pqxx::result::const_iterator row,
pqxxobject::transaction& tran)
{
row_ptr p(new Row);
p->convert_impl(row, tran); // protected
p->row_base::m_state = STATE_INITIALISED; // private
return p;
}

virtual void convert_impl(pqxx::result::const_iterator row,
pqxxobject::transaction& tran) = 0;

}; // class row

Here, in the static create() method, row_base::m_state is a private
(enum) data member of the base class, yet I can assign it directly.
However, convert_impl() is a pure virtual function which is public
here and protected in the deriving class, but I get an error when I
compile:

places.cc: In static member function `static std::auto_ptr<_Tp1>
pqxxobject::row<Row>::create(pqxx::result::const_iterator,
pqxxobject::transaction&) [with Row = Place]':
.../pqxx-object/table.h:172: instantiated from `std::auto_ptr<std::list<Row, std::allocator<_CharT> > > pqxxobject::table<Row>::find_many(const std::string&) [with Row = Place]'
places.cc:207: instantiated from here
places.cc:175: error: `virtual void
Place::convert_impl(pqxx::result::const_iterator, pqxxobject::transaction&)'
is protected
.../pqxx-object/row.h:97: error: within this context

row.h:97 is the "p->convert_impl(row, tran);" line, above.

I can't see the rationale between being able to access private data
members, but not protected methods (which are actually public in the
row<> class)!


I would probably be better making create() call a specialised
protected constructor, but I'm interested in learning why the above
doesn't work.


Thanks,
Roger
 
R

Rolf Magnus

Roger said:
The C++ book I have to hand (Liberty and Horvath, Teach yourself C++
for Linux in 21 Days--I know there are better) states that "static
member functions cannot access any non-static member variables".
However, this doesn't seem entirely correct.

You're right. If your static member function has an object of the class,
it can access member variables of that object.
It also doesn't mention whether static member functions can access
protected and private member data and methods (and I couldn't spot
this in the FAQ).

It doesn't matter if the member is static or not. Any member function
can access any protected and private member of the same class.
I have a class row<Row> which derives from row_base:

template<typename Row>
class row : public row_base
{
public:
typedef std::auto_ptr<Row> row_ptr;

row(): row_base() {}

row(row_state status, bool modified=false):
row_base(status, modified) {}

virtual ~row() {}

static row_ptr create(pqxx::result::const_iterator row,
pqxxobject::transaction& tran)
{
row_ptr p(new Row);
p->convert_impl(row, tran); // protected
p->row_base::m_state = STATE_INITIALISED; // private
return p;
}

virtual void convert_impl(pqxx::result::const_iterator row,
pqxxobject::transaction& tran) = 0;

}; // class row

Here, in the static create() method, row_base::m_state is a private
(enum) data member of the base class, yet I can assign it directly.
However, convert_impl() is a pure virtual function which is public
here and protected in the deriving class, but I get an error when I
compile:

places.cc: In static member function `static std::auto_ptr<_Tp1>
pqxxobject::row<Row>::create(pqxx::result::const_iterator,
pqxxobject::transaction&) [with Row = Place]':
../pqxx-object/table.h:172: instantiated from
`std::auto_ptr<std::list<Row, std::allocator<_CharT> > >
pqxxobject::table<Row>::find_many(const std::string&) [with Row =
Place]'
places.cc:207: instantiated from here
places.cc:175: error: `virtual void
Place::convert_impl(pqxx::result::const_iterator,
pqxxobject::transaction&)' is protected
../pqxx-object/row.h:97: error: within this context

row.h:97 is the "p->convert_impl(row, tran);" line, above.

I can't see the rationale between being able to access private data
members, but not protected methods (which are actually public in the
row<> class)!

They are public in the row<> class, but you are declaring your pointer
as row_ptr, which in your case is an auto_ptr<Place>. So you're
accessing the object through a pointer to Place, where, as you say, the
member is protected, i.e. only Place itself and classes derived from
that can access it.
 
M

Martijn Lievaart

You're right. If your static member function has an object of the class,
it can access member variables of that object.

I guess it's a clumsy way of saying you have no this-pointer.

M4
 
R

Rolf Magnus

Martijn said:
I guess it's a clumsy way of saying you have no this-pointer.

It's not clumsy, it's just more explicit. Anyway, saying that static
members cannot access non-static members is just plain wrong.
 
M

Martijn Lievaart

It's not clumsy, it's just more explicit. Anyway, saying that static
members cannot access non-static members is just plain wrong.

My bad, I was referring to the original statement, not your explanation. I
should have made that clearer.

M4
 
C

c++novice

Roger Leigh said:
The C++ book I have to hand (Liberty and Horvath, Teach yourself C++
for Linux in 21 Days--I know there are better) states that "static
member functions cannot access any non-static member variables".

The static functions can address only the static data of a class;
non-static data are unavailable to these functions. If non-static data
could be addressed, to which object would they belong? Any attempt
to access a normal class member will generate a compile time
error. Similarly, static functions cannot call non-static functions of
the class. All this is caused by the fact that static functions have
no this pointer.


However, this doesn't seem entirely correct. It also doesn't mention
whether static member functions can access protected and private
member data and methods (and I couldn't spot this in the FAQ).

I have a class row<Row> which derives from row_base:

template<typename Row>
class row : public row_base
{
public:
typedef std::auto_ptr<Row> row_ptr;

row(): row_base() {}

row(row_state status, bool modified=false):
row_base(status, modified) {}

virtual ~row() {}

static row_ptr create(pqxx::result::const_iterator row,
pqxxobject::transaction& tran)
{
row_ptr p(new Row);
p->convert_impl(row, tran); // protected
p->row_base::m_state = STATE_INITIALISED; // private
return p;
}

virtual void convert_impl(pqxx::result::const_iterator row,
pqxxobject::transaction& tran) = 0;

}; // class row

Here, in the static create() method, row_base::m_state is a private
(enum) data member of the base class, yet I can assign it directly.
However, convert_impl() is a pure virtual function which is public
here and protected in the deriving class, but I get an error when I
compile:

places.cc: In static member function `static std::auto_ptr<_Tp1>
pqxxobject::row<Row>::create(pqxx::result::const_iterator,
pqxxobject::transaction&) [with Row = Place]':
../pqxx-object/table.h:172: instantiated from `std::auto_ptr<std::list<Row, std::allocator<_CharT> > > pqxxobject::table<Row>::find_many(const std::string&) [with Row = Place]'
places.cc:207: instantiated from here
places.cc:175: error: `virtual void
Place::convert_impl(pqxx::result::const_iterator, pqxxobject::transaction&)'
is protected
../pqxx-object/row.h:97: error: within this context

row.h:97 is the "p->convert_impl(row, tran);" line, above.

I can't see the rationale between being able to access private data
members, but not protected methods (which are actually public in the
row<> class)!


I would probably be better making create() call a specialised
protected constructor, but I'm interested in learning why the above
doesn't work.


Thanks,
Roger

--
Roger Leigh

Printing on GNU/Linux? http://gimp-print.sourceforge.net/
GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.
 
N

Nick Hounsome

c++novice said:
Roger Leigh <${roger}@invalid.whinlatter.uklinux.net.invalid> wrote in

The static functions can address only the static data of a class;
non-static data are unavailable to these functions. If non-static data
could be addressed, to which object would they belong? Any attempt
to access a normal class member will generate a compile time
error. Similarly, static functions cannot call non-static functions of
the class. All this is caused by the fact that static functions have
no this pointer.

No they can access any data and methods of the class - they just don't have
a 'this'.
However, this doesn't seem entirely correct. It also doesn't mention
whether static member functions can access protected and private
member data and methods (and I couldn't spot this in the FAQ).

I have a class row<Row> which derives from row_base:

template<typename Row>
class row : public row_base
{
public:
typedef std::auto_ptr<Row> row_ptr;

row(): row_base() {}

row(row_state status, bool modified=false):
row_base(status, modified) {}

virtual ~row() {}

static row_ptr create(pqxx::result::const_iterator row,
pqxxobject::transaction& tran)
{
row_ptr p(new Row);
p->convert_impl(row, tran); // protected
p->row_base::m_state = STATE_INITIALISED; // private
return p;
}

virtual void convert_impl(pqxx::result::const_iterator row,
pqxxobject::transaction& tran) = 0;

}; // class row

Here, in the static create() method, row_base::m_state is a private
(enum) data member of the base class, yet I can assign it directly.
However, convert_impl() is a pure virtual function which is public
here and protected in the deriving class, but I get an error when I
compile:

places.cc: In static member function `static std::auto_ptr<_Tp1>
pqxxobject::row<Row>::create(pqxx::result::const_iterator,
pqxxobject::transaction&) [with Row = Place]':
../pqxx-object/table.h:172: instantiated from
`std::auto_ptr said:
places.cc:207: instantiated from here
places.cc:175: error: `virtual void
Place::convert_impl(pqxx::result::const_iterator, pqxxobject::transaction&)'
is protected
../pqxx-object/row.h:97: error: within this context

row.h:97 is the "p->convert_impl(row, tran);" line, above.

Are you certain because it seems to me that you shouldn't even be able to
create a row since you have
declared convert_impl pure virtual.
 
R

Rolf Magnus

c++novice said:
The static functions can address only the static data of a class;
non-static data are unavailable to these functions. If non-static data
could be addressed, to which object would they belong?

Any object that is available to the function.
Any attempt
to access a normal class member will generate a compile time
error. Similarly, static functions cannot call non-static functions of
the class.

Just like a non-member-function can access non-static data of a class, a
static member function can. If you're still not convinced, explain
this:

#include <iostream>

class X
{
public:
static void foo(const X& x)
{
std::cout << x.text;
}

const char* text;
};

int main()
{
X x;
x.text = "Hello world!\n";
X::foo(x);
}

X::text is a non-static member of X, and still the static member
function does access it.
All this is caused by the fact that static functions have
no this pointer.

Right, they have no this pointer, but they can still access non-static
members of the class if they get an instance of that class. They just
are not called for a specific instance.
 
C

c++novice

Rolf Magnus said:
Any object that is available to the function.


Just like a non-member-function can access non-static data of a class, a
static member function can. If you're still not convinced, explain
this:

#include <iostream>

class X
{
public:
static void foo(const X& x)
{
std::cout << x.text;
}

const char* text;
};

int main()
{
X x;
x.text = "Hello world!\n";
X::foo(x);
}

X::text is a non-static member of X, and still the static member
function does access it.

U r very much right because here an object of type X is passed in
static member function foo()as a parameter,
But foo() is not directly accessing the member like
std::cout << text;
 
R

Roger Leigh

Rolf Magnus said:
It's not clumsy, it's just more explicit. Anyway, saying that static
members cannot access non-static members is just plain wrong.

Much of the book is like that. I found it fairly readable for the
basics of the language, but it leaves a lot of questions unanswered,
and the devil is always in the details.

I did get a copy of Stroustrup's TCPL from the library at the same
time, but as a C programmer with no OO knowledge, I was out of my
depth several pages into the introduction!! It would probably be OK
now I have a decent grasp of the language, but the 21 days books was
far more understandable at the time.
 
R

Roger Leigh

Rolf Magnus said:
Roger said:
I have a class row<Row> which derives from row_base:

template<typename Row>
class row : public row_base
{
public:
typedef std::auto_ptr<Row> row_ptr;

row(): row_base() {}

row(row_state status, bool modified=false):
row_base(status, modified) {}

virtual ~row() {}

static row_ptr create(pqxx::result::const_iterator row,
pqxxobject::transaction& tran)
{
row_ptr p(new Row);
p->convert_impl(row, tran); // protected
p->row_base::m_state = STATE_INITIALISED; // private
return p;
}

virtual void convert_impl(pqxx::result::const_iterator row,
pqxxobject::transaction& tran) = 0;

}; // class row

Here, in the static create() method, row_base::m_state is a private
(enum) data member of the base class, yet I can assign it directly.
However, convert_impl() is a pure virtual function which is public
here and protected in the deriving class, but I get an error when I
compile: [...]
I can't see the rationale between being able to access private data
members, but not protected methods (which are actually public in the
row<> class)!

They are public in the row<> class, but you are declaring your pointer
as row_ptr, which in your case is an auto_ptr<Place>. So you're
accessing the object through a pointer to Place, where, as you say, the
member is protected, i.e. only Place itself and classes derived from
that can access it.

Ah, that makes sense!

I've now got it working, but only after discovering a wart in the
language: the base class is a template and if I declare a pure virtual
(or virtual) function in the template, when I call the function it
does not call the derived version. It appears that virtual does not
work with templates at all :-\.

I've come up with two solutions: declare the function in the deriving
class public, so the template can call it directly (not desirable), or
keep it protected/private and make the base class a friend, so it can
call them even though they are protected (better, but still not
clean enough for my liking).

Is there a better alternative to these approaches? Basically, I'd
like to be able to fake virtual to achieve this effect:

template<typename T>
class foo {
public:
void func() { func_impl(); }
private:
virtual void func_impl();
}

class bar : public foo<int> {
private:
virtual void func_impl();
}

i.e. when I do this:
bar c;
c.func()
c.func_impl() gets called by foo<int>::func().

Thanks,
Roger
 
J

Jeff Schwab

Roger said:
I did get a copy of Stroustrup's TCPL from the library at the same
time, but as a C programmer with no OO knowledge, I was out of my
depth several pages into the introduction!! It would probably be OK
now I have a decent grasp of the language, but the 21 days books was
far more understandable at the time.

Try skipping the intro. If you already have some familiarity with C,
the first few chapters of TC++PL should be mostly review for you, and
get you up to speed quickly on C++ as a "better C."
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,981
Messages
2,570,187
Members
46,731
Latest member
MarcyGipso

Latest Threads

Top