954,499 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

User declared object type?

I would like to declare the type of an object based on user input.

Ie. I would like to do the following:

string obj = //get from command line arguments
	if(Format == "obj")
	{
		ObjFile Obj;
		Obj.Read(InputFile);
		Obj.DoSomething();			
		Obj.Write(OutputFile);
	}

	else if (Format == "vtk")
	{
		VtkFile Vtk;
		Vtk.Read(InputFile);
		Vtk.DoSomething();
		Vtk.Write(OutputFile);
	}

//the list goes on...


But to possibly 10-ish file types, without having a 5 page long list of if's. Is this possible? Something like

//somehow make an object of the correct type called GoodObject
GoodObject.Read(InputFile);
GoodObject.DoSomething();
GoodObject.Write(OutputFile);


Thanks,

Dave

daviddoria
Posting Virtuoso
1,996 posts since Feb 2008
Reputation Points: 437
Solved Threads: 204
 

If each class derives from the same base class inheriting virtual functions then it may be possible to do something with pointers that looks vaguely like:

class base
   virtual A()
   virtual B()
   virtual C()
class V : public base
    A()
    B()
    C()
class C: public base
    A()
    B()
    C()
int main()
base * ptr;
string CLArg[];
int numComm;
for(i = 0; i < numComm; ++i)
  if(CLArg[i] == "V")
    classType = 1;
  else if(CLArg[i] == "C")
    classType = 2;

  switch(classType) 
    case 1: ptr = new V;
    case 2: ptr = new C;

    ptr->A();
    ptr->B();
    ptr->C();
Lerner
Nearly a Posting Maven
2,382 posts since Jul 2005
Reputation Points: 739
Solved Threads: 396
 

hmm so even thought the pointer is a base*, you can use ptr = new V?

daviddoria
Posting Virtuoso
1,996 posts since Feb 2008
Reputation Points: 437
Solved Threads: 204
 

Try this (add includes):

using std::flush;
using std::cout;
using std::endl;
using std::cin;

class Aircraft {
public:
    Aircraft() { cout << "Aircraft is up!" << endl; }
    virtual ~Aircraft() {}
    virtual void doSomething() = 0;
};

class Fighter: public Aircraft {
public:
    ~Fighter() { cout << "Fighter landed." << endl; }
    void doSomething() { cout << "Z-z-z-z..." << endl; }
};

class Bomber: public Aircraft {
public:
    ~Bomber() { cout << "Bomber crashed." << endl; }
    void doSomething() { cout << "Zh-zh-BANG" << endl; }
};

int main()
{
    Aircraft* plane;
    char reply;

    while (cout << "Enter f|b|q: " << flush, cin >> reply) {
        switch (reply) {
        case 'f':   plane = new Fighter;break;
        case 'b':   plane = new Bomber; break;
        default: plane = 0; break;
        }
        if (plane == 0)
            break;
        plane->doSomething();
        delete plane;
        cin.ignore(1000,'\n');
    }
    return 0;
}
ArkM
Postaholic
2,001 posts since Jul 2008
Reputation Points: 1,234
Solved Threads: 348
 

I still have the same question - why can you use

new Fighter

to assign an Aircraft variable?

daviddoria
Posting Virtuoso
1,996 posts since Feb 2008
Reputation Points: 437
Solved Threads: 204
 

Because any Fighter object IS an Aircraft too, look at

class Fighter: public /* inherites from */ Aircraft

So my plane pointer refers to an Aircraft of type Fighter, then it refers to another Aircraft - bomber of type Bomber.
Both a fighter and a bomber are aircrafts.

But not vice versa. It's wrong code:

Aircraft* plane = new Fighter;
...
Fighter* f15c = plane;

You can't directly assign a pointer to base class to a pointer to derived class. May be the 1st one refers to bomber object now...
In actual fact sometimes you can do that via dynamic_cast construct, but it's another story...

ArkM
Postaholic
2,001 posts since Jul 2008
Reputation Points: 1,234
Solved Threads: 348
 

I'm convinced that works, but I'm still not sure why.

It is my understanding that when you make a pointer Aircraft* that a pointer is created which points to an address of the size required to hold all of the members of Aircraft. However, there are additional members (more than Aircraft) in Fighter because Fighter inherits all of Aircrafts members and then defines additional ones. So it seems that the Aircraft pointer would be "too small" to fit everything in Figher. Am I way off here?

daviddoria
Posting Virtuoso
1,996 posts since Feb 2008
Reputation Points: 437
Solved Threads: 204
 

A pointer does not fit anything except an address. It can't be "too small". It is a pointer - that's all.

If you dereference (with unary operator *) a pointer to Aircraft, you get only common part of all Aircrafts. For example, if the plane pointer refers to the Fighter object, *plane expression gets only Aircraft object part of that fighter...

But if you call virtual (only virtual) member functions via base class pointer (or via reference to base class) then true derived class object functions are called. Why? It's funny but the most silly answer is correct: that's C++ rules!

It's C++ implementation of the OOP polymorphism notion.

ArkM
Postaholic
2,001 posts since Jul 2008
Reputation Points: 1,234
Solved Threads: 348
 

I see - thats what I meant by "too small", that when you dereference a derived class which is of type Aircraft* then you wouldn't get everything, but I guess that is correct!

Thanks for your help!
Dave

daviddoria
Posting Virtuoso
1,996 posts since Feb 2008
Reputation Points: 437
Solved Threads: 204
 
I see - thats what I meant by "too small", that when you dereference a derived class which is of type Aircraft* then you wouldn't get everything, but I guess that is correct! Dave


Please, be more thorough: when you dereference a pointer to base class referred to an object of derived class...
It's so called slicing.

ArkM
Postaholic
2,001 posts since Jul 2008
Reputation Points: 1,234
Solved Threads: 348
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You