"trivial" problem with template method pattern

R

rogo

Ok, when I began to implement it, I thought it should be
straightforward and easy. I'm not sure whats wrong with the following
code:

class A
{
public:
A() {}
int get()
{
int a;
get(a);
return a;
}
protected:
virtual void get(int&) = 0;
};

class B : public A
{
public:
B(int a) : b(a) {}
private:
void get(int& a)
{
a = b;
}
int b;
};

int main() {
B b(1);
b.get();// thats a problem, and I dont know why
}

For some reason I dont understand yet the compiler can't "find" the
inherited methode "int get()". I use g++ version 4.1.2 20070925.
 
J

Jim Langston

rogo said:
Ok, when I began to implement it, I thought it should be
straightforward and easy. I'm not sure whats wrong with the following
code:

class A
{
public:
A() {}
int get()
{
int a;
get(a);
return a;
}
protected:
virtual void get(int&) = 0;
};

When the complier gets here it sees everything that A has, and there is no
::get(int) or A::get(int). In other words, there is no get(int) within
scope that get() can call.

Inherited classes can call functions from base classes, but base classes can
not normally call functions within derived classes.
 
R

red floyd

rogo said:
Ok, when I began to implement it, I thought it should be
straightforward and easy. I'm not sure whats wrong with the following
code:

class A
{
public:
A() {}
int get()
{
int a;
get(a);
return a;
}
protected:
virtual void get(int&) = 0;
};

class B : public A
{
public:
B(int a) : b(a) {} using A::get();
private:
void get(int& a)
{
a = b;
}
int b;
};

int main() {
B b(1);
b.get();// thats a problem, and I dont know why
}

For some reason I dont understand yet the compiler can't "find" the
inherited methode "int get()". I use g++ version 4.1.2 20070925.

Behavior is correct. The declaration of B::get(int&) hides all other
instances of get() for B. You have two choices: put a using declaration
in all your child classes (see above), or rename get(int&). The second
is a better solution, especially since get(int&) is private.
 
K

Keith Willis

Inherited classes can call functions from base classes, but base classes can
not normally call functions within derived classes.

I think I take issue with you regarding the phrasing of that; surely
the entire _point_ of virtual functions, for example, is to allow the
derived class to replace or augment the implementation provided by the
base class, i.e. the base class is calling functions withing the
derived class?
 
J

Jim Langston

Keith Willis said:
I think I take issue with you regarding the phrasing of that; surely
the entire _point_ of virtual functions, for example, is to allow the
derived class to replace or augment the implementation provided by the
base class, i.e. the base class is calling functions withing the
derived class?

No. Because with a polymorphism you create a derived class, not a base
class. It is the derived class's functions you are calling not the base
classes.

He is trying to call a base class function that calls a derived classes
function, which is normally not done. A base class knows nothing of the
classes that derive from it. The derived classes know of the base class
they derive from.
 
R

rogo

Jim said:
A base class knows nothing of the
classes that derive from it. The derived classes know of the base class
they derive from.

That's not true. The declaration of "virtual void get(int&) = 0;"
ensures that subclasses have to implement the declared method. So the
base class knows a method implementation exists in all derived
classes.
He is trying to call a base class function that calls a derived classes
function, which is normally not done.

I object to that too. It's the concept of the Template Method Pattern
(1) combined with standard inheritance. It should work and in other
object oriented languages it does. So, why not in C++?

(1) Gamma, E. et alii (2004): Design Patterns Elements of Reusable
Object-Oriented Software, 31st Printing, Boston u.a.
 
R

rogo

red said:
Behavior is correct. The declaration of B::get(int&) hides all other
instances of get() for B. You have two choices: put a using declaration
in all your child classes (see above), or rename get(int&). The second
is a better solution, especially since get(int&) is private.

Your second solution is exactly what I did. But I'm still curious why
A::get() gets hidden for B. Is this behaviour standard compliant?
 
J

Jim Langston

rogo said:
That's not true. The declaration of "virtual void get(int&) = 0;"
ensures that subclasses have to implement the declared method. So the
base class knows a method implementation exists in all derived
classes.


I object to that too. It's the concept of the Template Method Pattern
(1) combined with standard inheritance. It should work and in other
object oriented languages it does. So, why not in C++?

(1) Gamma, E. et alii (2004): Design Patterns Elements of Reusable
Object-Oriented Software, 31st Printing, Boston u.a.

The question isn't what should work, but what does work. My statements are
applying to how C++ works, not how other languages work or how you think C++
should work. There is enough to dicuss in C++ currently without discussing
what shoulda, woulda, coulda been in it. comp.std.c++ is the forum to
discuss those issues.
 
J

James Kanze

red floyd schrieb:
Your second solution is exactly what I did. But I'm still
curious why A::get() gets hidden for B. Is this behaviour
standard compliant?

It's what the standard requires. The situation is somewhat
complicated by ADL, but in general, lookup works its way through
a series of scopes, stopping at the first scope where it finds
the symbol.

The reason for this simple. Consider the following code:

class Base
{
public:
virtual void f() = 0 ;

} ;
class Derived : public Base
{
public:
void f() { call g( 'a' ) ; }

private:
void g( int ) ;
} ;

Obviously, the implementation of f() wants to use the private
function g, which is part of the implementation. Now, what
will happen if Base is modified to add a new function:

class Base
{
public:
void g( char ) { f() ; }
}

Adding such a simple function to base shouldn't break the
derived classes, should it? (If name lookup didn't stop in
when it found the g in Derived, this change would result in
infinite recursion in Derived.)
 
T

Tadeusz Kopec

Jim said:
rogo said:
Jim Langston schrieb: [snip]
He is trying to call a base class function that calls a derived classes
function, which is normally not done.
I object to that too. It's the concept of the Template Method Pattern
(1) combined with standard inheritance. It should work and in other
object oriented languages it does. So, why not in C++?

(1) Gamma, E. et alii (2004): Design Patterns Elements of Reusable
Object-Oriented Software, 31st Printing, Boston u.a.

The question isn't what should work, but what does work. My statements are
applying to how C++ works, not how other languages work or how you think C++
should work. There is enough to dicuss in C++ currently without discussing
what shoulda, woulda, coulda been in it. comp.std.c++ is the forum to
discuss those issues.

Do you mean his attempt to implement the Template Method Pattern,
besides for his mistake with hiding a name of the function, is wrong in
C++? That it's something wrong with such code:

class Base
{
public:
void f()
{
g();
}
private:
virtual void g() = 0;
};

class Derived: public Base
{
private:
virtual void g()
{
// some implementation
}
};

If so, I strongly object.
 
J

Jim Langston

Tadeusz Kopec said:
Jim said:
rogo said:
Jim Langston schrieb: [snip]
He is trying to call a base class function that calls a derived classes
function, which is normally not done.
I object to that too. It's the concept of the Template Method Pattern
(1) combined with standard inheritance. It should work and in other
object oriented languages it does. So, why not in C++?

(1) Gamma, E. et alii (2004): Design Patterns Elements of Reusable
Object-Oriented Software, 31st Printing, Boston u.a.

The question isn't what should work, but what does work. My statements
are
applying to how C++ works, not how other languages work or how you think
C++
should work. There is enough to dicuss in C++ currently without
discussing
what shoulda, woulda, coulda been in it. comp.std.c++ is the forum to
discuss those issues.

Do you mean his attempt to implement the Template Method Pattern,
besides for his mistake with hiding a name of the function, is wrong in
C++? That it's something wrong with such code:

class Base
{
public:
void f()
{
g();
}
private:
virtual void g() = 0;
};

class Derived: public Base
{
private:
virtual void g()
{
// some implementation
}
};

If so, I strongly object.

Here Base is calling one of it's OWN methods, which may (will) be
overridden.
 

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,776
Messages
2,569,603
Members
45,188
Latest member
Crypto TaxSoftware

Latest Threads

Top