LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-07-2005, 10:20 PM   #1
niteshadw
Member
 
Registered: Sep 2002
Distribution: CentOS
Posts: 170

Rep: Reputation: 15
C++ and inheritance question


Hello, I have this base class and a dreived class...below are the highlights and what not. I'm having trouble accessing the private memebers of the derived class when I use the following code in main:

Code:
int main(){
	
	Vehicle* pArray[3];
	pArray[0] = new Vehicle;
	pArray[1] = new SUV;
	pArray[2] = new SUV;


	for(int i = 0; i < 3; i++){
		pArray[i]->setMilage(rand());
		pArray[i]->display();
		pArray[i]->drive();
		cout << endl;
	} //for
}
I want to be able to set fourWDStatus using an accessor function to true which is found in the SUV derived class by using pArray[1]->...am I doing something wrong or missing something? Below is the code for the two classes:

Code:
class Vehicle{
protected:
	int* VIN;
	double* milage;

public:
	Vehicle() {VIN = new int(NULL); milage = new double(NULL);}

	Vehicle(const Vehicle& rhs): VIN(new int()), milage(new double()) {*this = rhs;}
	Vehicle& operator =(const Vehicle& rhs);
	virtual ~Vehicle(){delete VIN, milage;}

	int getVIN() const {return *VIN;}
	double getMilage() const {return *milage;}

	void setVIN(int v) {VIN = new int(v);}
	void setMilage(double m) {milage = new double(m);}

	virtual void display();
	double calcGasUsed(double);
	void drive();

};

/////////////////////////////////////////////////////////////

class SUV: public Vehicle{
private:
	bool* fourWDStatus;
	double* fourWDGasMileage;

public:
	SUV() {fourWDStatus = new bool(NULL); fourWDGasMileage = new double(NULL);}
	virtual ~SUV() {delete fourWDStatus, fourWDGasMileage;}

	int getFourWDStatus() const {return *fourWDStatus;}
	double getFourWDGasMileage() const {return *fourWDGasMileage;}

	void setFourWDStatus(bool driveStatus) {fourWDStatus = new bool(driveStatus);}
	void setFourWDGasMileage(double gasMileage) {fourWDGasMileage = new double(gasMileage);}

	virtual void display();
	double calcGasUsed(double);

};
If pArray[1]->setFourWDStatus(true); an incorred way, how is it changed? Becuase if I do:
Code:
	SUV t;
	t.setFourWDStatus(true);
Then it works fine....I dunno...is the constructor the only way?...Thank you =)

Last edited by niteshadw; 08-07-2005 at 10:29 PM.
 
Old 08-08-2005, 12:19 AM   #2
lowpro2k3
Member
 
Registered: Oct 2003
Location: Canada
Distribution: Slackware
Posts: 340

Rep: Reputation: 30
I read through your code, but I'm a little confused at your question. The first code block you posted (main(...)), is that code working and compiling properly? Then you go on to talk about calling your set4wdriver() method, which isn't a part of main.

I could be a little rusty on inheritance, and correct me if I'm wrong (I'm just trying to help), but aren't you trying to employ some broken polymorphism below:

Code:
Vehicle* pArray[3];
pArray[0] = new Vehicle;
pArray[1] = new SUV;
pArray[2] = new SUV;


for(int i = 0; i < 3; i++){
	pArray[i]->setMilage(rand());
	pArray[i]->display();
	pArray[i]->drive();
	cout << endl;
} //for
I think you should organize your methods a little differently, employing virtual functions:

Code:
class Vehicle
{
...
    // this will be overridden by derived classes
    virtual void setMilage(...) {
        // perform Vehicle-specific milage calculations
    }
};

class SUV : public Vehicle
{
...
    // override base class setMilage()
    virtual void setMilage(...) {
        // perform SUV-specific milage calculations
    }
};
Now going back to your main() section, you shouldn't need a special function like set4WheelDriveMilage, because polymorphism will take care of calling the right method for you, based on the object type:

Code:
Vehicle* pArray[3];
pArray[0] = new Vehicle;
pArray[1] = new SUV;
pArray[2] = new SUV;


for(int i = 0; i < 3; i++){
	pArray[i]->setMilage(rand());
	pArray[i]->display();
	pArray[i]->drive();
	cout << endl;
} //for
This should work as you expect, assuming you declare display() and drive() as virtual functions as well. Since you properly declare your array of pointers as an array of base class pointers, and then you create derived objects on base class pointers, polymorphism will look at the virtual function table and call the right function for you in your for loop.

Post questions/comments on what you think, thats how I'd structure my program but I'm a tiny bit rusty on C++ inheritance.

- lowpro2k3
 
Old 08-08-2005, 07:08 AM   #3
carl.waldbieser
Member
 
Registered: Jun 2005
Location: Pennsylvania
Distribution: Kubuntu
Posts: 197

Rep: Reputation: 32
I think niteshadw's question may be, "why won't the compiler let me call setFourWDStatus() from my base class pointer?" The answer is because your base class does not define that function as a virtual function-- it does not define that function at all!

You would need to cast your pointer to the derived class to make your classes work as they stand now. Depending on your aims, there are several ways to proceed.

One way is to put all the functions you could possible want to call into the base class as virtual functions.
 
Old 08-08-2005, 07:27 AM   #4
niteshadw
Member
 
Registered: Sep 2002
Distribution: CentOS
Posts: 170

Original Poster
Rep: Reputation: 15
Yes, everything in main() works thus far, but I want to be able to put one of the two SUVs in four wheel drive mode so when its in four wheel drive mode it calculates the gas usage a different way...its just simple code to try to learn iherintance/polymorphsism...so since pArray[1] is a suv, I should be able to see the private memebers of the class, but I only see those that belong to the base class...so basically how can I set the pArray[1] to four wheel drive? Thanks
 
Old 08-08-2005, 09:53 AM   #5
lowpro2k3
Member
 
Registered: Oct 2003
Location: Canada
Distribution: Slackware
Posts: 340

Rep: Reputation: 30
sorry, working, no time to edit.

good luck

Last edited by lowpro2k3; 08-08-2005 at 10:00 AM.
 
Old 08-08-2005, 03:36 PM   #6
CroMagnon
Member
 
Registered: Sep 2004
Location: New Zealand
Distribution: Debian
Posts: 900

Rep: Reputation: 33
carl gave you the right answer, just in case you missed it. You need to do something like this:
Code:
((SUV *)pArray[1])->setFourWDStatus(true);
Excuse me if I've messed up the syntax, I don't really know C++ that well. The point is, even though you initialised pArray[1] as an SUV, pArray is declared (earlier) as an array of Vehicle pointers, and the compiler is stopping you from trying to use a Vehicle as a specific subclass. Effectively, you have to tell the compiler "Yes, I really do want to use this Vehicle as an SUV".
 
Old 08-08-2005, 04:04 PM   #7
deiussum
Member
 
Registered: Aug 2003
Location: Santa Clara, CA
Distribution: Slackware
Posts: 895

Rep: Reputation: 32
A safer way of doing the casting C++ style is:

Code:
SUV* pSUV = dynamic_cast<SUV*>(pArray[1]);
if (pSUV)
{ 
    pSUV->setFourWDStatus(true)
}
Your code has some memory leak problems too, and might not be the best way to design it, but I'll leave those topics for another time...
 
Old 08-08-2005, 04:43 PM   #8
lowpro2k3
Member
 
Registered: Oct 2003
Location: Canada
Distribution: Slackware
Posts: 340

Rep: Reputation: 30
Quote:
Originally posted by niteshadw
Yes, everything in main() works thus far, but I want to be able to put one of the two SUVs in four wheel drive mode so when its in four wheel drive mode it calculates the gas usage a different way...its just simple code to try to learn iherintance/polymorphsism...so since pArray[1] is a suv, I should be able to see the private memebers of the class, but I only see those that belong to the base class...so basically how can I set the pArray[1] to four wheel drive? Thanks
OK, basically you're trying to accomplish polymorphism with code like this:

Code:
int main(){
	
	Vehicle* pArray[3];
	pArray[0] = new Vehicle;
	pArray[1] = new SUV;
	pArray[2] = new SUV;


	for(int i = 0; i < 3; i++){
		pArray[i]->setMilage(rand());
		pArray[i]->display();
		pArray[i]->drive();
		cout << endl;
	} //for
}
Specifically, you are expecting C++ to 'do the Right Thing' in your for loop. If you're not trying to accomplish polymorphism thats fine, and nobodies forcing you too, but your code in main IS trying to use it.

First look at your array declaration. Your declaring an array of base class pointers. Then you're initializing 2 of the 3 elements to derived class objects.

If you listen to the advice you're given, and learn a little about polymorphism theres no need for functions like 'setFourWheelDriveMilage' and that kind of class-specific stuff, and if you code you're base classes right you can save alot of typing.

Heres a very simple example of polymorphism:

Code:
class Vehicle
{
  protected:
    float milage_;
  public:
    Vehicle(float m = 10000.00): milage_(m) {}
    virtual void print() const {
      cout << "I am a Vehicle object\n";
    }
};

class SportsCar : public Vehicle
{
  protected:
    string color_;
  public:
    SportsCar(float m = 10000.00, string c = ""): Vehicle(m), color_(c) {}
    virtual void print() const {
      cout << "I am a SportsCar object\n";
    }
};

int main()
{
  Vehicle* t[2];
  t[0] = new Vehicle;
  t[1] = new SportsCar;

  for(int i = 0; i < 2; i++)
    t[i]->print();

  return 0;
}
Code:
[shell]$ g++ -o vehicles vehicles.cpp
[shell]$ ./vehicles
I am a Vehicle object
I am a SportsCar object
Take a quick look at the classes, then take a bigger look at the bold red code. How does C++ know which function to call? How does it know whether its operating on a SportsCar or a Vehicle? It calls the right function... How does it do it?

The answer is virtual function tables and polymorphism. I won't try and act like Bjarne, and define polymorphism for you, plenty of C++ books do that for you. But the point is, by declaring those class methods virtual, C++ then knows where to look to determine which function gets called.

If you don't care about any of that, why don't you just write your code the 'normal' way?

Code:
Vehicle* t = new Vehicle;
SUV* s = new SUV;
// ...
Anyway I hope you learned something because it took a while to type. Enjoy.

- lowpro2k3

Last edited by lowpro2k3; 08-08-2005 at 04:44 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
file inheritance tulip4heaven Linux - Networking 1 02-24-2005 02:30 AM
python inheritance towlie Programming 3 09-23-2004 12:13 AM
inheritance kalleanka Programming 4 02-29-2004 07:19 PM
OOP / Python inheritance question usernamenumber Programming 1 12-02-2003 10:21 PM
sub-shell inheritance drum1975 Linux - General 4 03-11-2002 03:50 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:37 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration