Should be using overloaded function, using parent function instead

This is kind of complicated so I will try to simplify my problem. Say I have a class Shape, and classes Triangle and Square extend it. Shape has a getColor function, and Square and Triangle both have their own getColor functions that overload it. Then I have a class Picture that has a Shape member in it. Let's say Picture has a function in it called listColors that calls its Shape's getColor function and returns its result along with some other data.

If I make a Triangle, then I make a Picture and put that Triangle in it as its Shape, then I call the Picture's listColors function, how do I make it use Triangle's getColor function instead of Shape's?

In other words, I have a class with a member that can be one of several different classes that all extend the same base class, and I want to use their overloaded functions instead of their base class's functions. How should I go about this?
ok if im reading right you have a base class: Shape and all the other things INHERIT it you said extend...not saying its wrong but that is java terminology in c++ the saying is inherit....it kinda sounds like you don't completely understand the concept when you have a base class(in your case Shape) and you inherit it with Triangle(in your case) then all methods that an object of type Shape would have Triangle also posses....so the getColor method of Shape should be the same for whatever the Shape is whether it be a triangle square trapozoid or rectangle! if you code is like you example just get rid of the extra code in you subclasses(triangle and square) and use your base class(Shape) for whatever function you have
I understand now that the way you describe it is how it works, and apologize for the mixup in terminology. The problem is that Triangle's getColor function works differently than Shape's getColor function, as does Square's. Is there a way to make Picture call the getColor function appropriate to whatever type of Shape the Shape inside it is, without forcing Picture to have members of every type of Shape?
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <vector>
#include <memory>

class Base
{
public:
    virtual void method() = 0;
    virtual ~Base() {}
};

class A : public Base
{
public:
    void method() { std::cout << "A::method()\n" ; }
};

class B: public Base
{
public:
    void method() { std::cout << "B::method()\n" ; }
};

int main()
{
    std::srand(std::time(0)) ;

    std::vector<Base*> objects ;

    for ( unsigned i=0; i<10; ++i )
    {
        Base * obj ;
        if ( rand() % 2 )
            obj = new A ;
        else
            obj = new B ;

        objects.push_back( obj ) ;
    }

    for ( unsigned i=0; i<objects.size(); ++i )
        objects[i]->method() ;

    for ( unsigned i=0; i<objects.size(); ++i )
        delete objects[i] ;
}


[Edit: Added virtual destructor to Base.]
Last edited on
Okay, I made Shape's getColor function virtual and deleted the definition. It wouldn't let me compile without defining it. I pasted the definition back, and it still used Shape's getColor function instead of Triangle's. I thought maybe your use of -> was important, but Picture stores a Shape, not a pointer to one. So, I used the pointer to it instead, and it still used Shape's virtual function instead of Triangle's. Then I restructured all my code so that, when the Picture is instantiated, it takes in a pointer to a Shape that points to a Triangle instead of just the Triangle itself, and then I used the -> on that pointer. It still used Shape's getColor function. If there was something else to the code, please let me know what it was and I apologize for missing it.

I've compiled what you gave me here and it does work. I am confused about what is different. Here's some pseudocode to describe what I'm doing.
in shape.h:
1
2
3
4
class Shape {
	Color c;
	virtual Color getColor(int foo = 1, int bar = 0) = 0;
};

in shape.cpp:
1
2
3
4
Color Shape::getColor(int foo, int bar) {
	cout << "Shape!" << endl;
	return c.doSomething(foo, bar);
}

in Triangle.h:
1
2
3
class Triangle:public Shape {
	Color getColor(int foo = 1, int bar = 0);
};

in Triangle.cpp:
1
2
3
4
Color Triangle::getColor(int foo, int bar) {
	cout << "Triangle!" << endl;
	return c.doSomethingDifferent(foo, bar);
}

in Picture.h:
1
2
3
4
5
6
7
class Picture {
	Shape* s;
	Color c;
	int importantFunction(int foo) {
		return mysteriousThings(s->getColor(), foo);
	}
}

and in main:
1
2
3
Picture p;
p.s = new Triangle();
int foo = p.importantFunction(2);

This will cout "Shape!".
Last edited on
Not sure if it's relevant, but when you declare a method to be pure virtual (that is, method() = 0;) you're not supposed to provide a definition for it
I thought maybe your use of -> was important, but Picture stores a Shape, not a pointer to one.


In order to get polymorphic behavior, you must use a pointer or a reference. If you use a Shape object, you get Shape behavior.

This is obviously not the code you compiled. If you did, indeed, assign a Triangle object to a Shape then the Triangleness of the object would be sliced off. If, on the other hand you used a pointer or reference and the provided code (after a few modifications so it would compile) and the result was "Shape!" your compiler would appear to be noncompliant.

Tested the following code with VC++11 and g++ 4.7.0 with correct "Triangle!" output.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>

using namespace std ;

class Color
{
public:

    Color& doSomething(int, int) { return *this; }
    Color& doSomethingDifferent(int, int) { return *this ; }
};

class Shape {
public:
    Color c;
    virtual Color getColor(int foo = 1, int bar = 0) = 0;
    virtual ~Shape() {}
};

Color Shape::getColor(int foo, int bar) {
    cout << "Shape!" << endl;
    return c.doSomething(foo, bar);
}

class Triangle:public Shape {
    Color getColor(int foo = 1, int bar = 0);
};

Color Triangle::getColor(int foo, int bar) {
    cout << "Triangle!" << endl;
    return c.doSomethingDifferent(foo, bar);
}

class Picture {
public:
    Shape* s;
    Color c;

    int mysteriousThings(Color, int f) { return f;}

    int importantFunction(int foo) {
        return mysteriousThings(s->getColor(), foo);
    }
};

int main()
{
    Picture p;
    p.s = new Triangle();
    int foo = p.importantFunction(2);
}


See also: http://www.gotw.ca/gotw/005.htm
Topic archived. No new replies allowed.