vendredi 18 avril 2014

OOP - fonctions virtuelles C++ base retournent type suggestions - Stack Overflow


I need a base class that gives me primitive type of data's pointer. I add a function in it. I derived types of class. I used void * to support all primitive types as a return type but it is like old C days. It is not good for OOP. Does one have an suggestion to do in a proper way in OOP?


#include <iostream>

class base {
public:
virtual void *getPtr() = 0;
virtual ~base() {};
};

class derivedAType : public base {
protected:
int _i;
public:
derivedAType(int i): _i(0) { _i = i; };
virtual ~derivedAType() {}

virtual void *getPtr() {
return static_cast<void *>(&_i);
}
};

class derivedBType : public base {
protected:
short _s;
public:
derivedBType(short s): _s(0) { _s = s; };
virtual ~derivedBType() {}

virtual void *getPtr() {
return static_cast<void *>(&_s);
}
};

int main()
{
base *b1 = new derivedAType(1203912);
base *b2 = new derivedBType(25273);

std::cout << "b1 : " << *(static_cast<int *>(b1->getPtr()))
<< "\nb2 : " << *(static_cast<short *>(b2->getPtr()))
<< std::endl;

delete b2;
delete b1;

return 0;
}



Make the base class a template class with the data type as the template variable


template<typename DataType>  
class base {
virtual DataType* getPtr() = 0;
//...
};

and


class derivedAType : public base<int>

But this changes base class to a template class which means you cant store them together, base<int> is different from base<short>


If this isnt acceptable, the other options is just a tad bit cleaner than your code but abt the same, refer to this question. Basically derived class return types can reflect their true type and i think it should get automatically converted to void*, so you dont have to manually cast the pointer.




Not sure about your problem. But maybe a double callback can help:


class Callback {
public:
virtual void do_int( int i ) const = 0;
virtual void do_short( short s ) const = 0;
/* ... */
}

class base {
public:
virtual void do_stuff(const Callback & c); /* will need a more telling name */
virtual ~base() {};
};

class derivedAType : public base {
protected:
int _i;
public:
derivedAType(int i): _i(0) { _i = i; };
virtual ~derivedAType() {}

virtual void do_stuff(const Callback & c) {
c.do_int( _i );
}
};

class derivedBType : public base {
protected:
short _s;
public:
derivedBType(short s): _s(0) { _s = s; };
virtual ~derivedBType() {}

virtual void do_stuff( const Callback & c) {
c.do_short( _s );
}
};

class print_callback : public Callback {
public:
virtual void do_int( int i ) const { std::cout << i; }
virtual void do_short( short s ) const { std::cout << s; }
}

int main() {
base *b1 = new derivedAType(1203912);
base *b2 = new derivedBType(25273);



std::cout << "b1 : ";
b1->do_stuff(print_callback());
std::cout << "\nb2 : ";
b2->do_stuff(print_callback());
std::cout << std::endl;

delete b2;
delete b1;

return 0;
}

Of course you can simplify this by just storing the created print callback, and using it twice.



I need a base class that gives me primitive type of data's pointer. I add a function in it. I derived types of class. I used void * to support all primitive types as a return type but it is like old C days. It is not good for OOP. Does one have an suggestion to do in a proper way in OOP?


#include <iostream>

class base {
public:
virtual void *getPtr() = 0;
virtual ~base() {};
};

class derivedAType : public base {
protected:
int _i;
public:
derivedAType(int i): _i(0) { _i = i; };
virtual ~derivedAType() {}

virtual void *getPtr() {
return static_cast<void *>(&_i);
}
};

class derivedBType : public base {
protected:
short _s;
public:
derivedBType(short s): _s(0) { _s = s; };
virtual ~derivedBType() {}

virtual void *getPtr() {
return static_cast<void *>(&_s);
}
};

int main()
{
base *b1 = new derivedAType(1203912);
base *b2 = new derivedBType(25273);

std::cout << "b1 : " << *(static_cast<int *>(b1->getPtr()))
<< "\nb2 : " << *(static_cast<short *>(b2->getPtr()))
<< std::endl;

delete b2;
delete b1;

return 0;
}


Make the base class a template class with the data type as the template variable


template<typename DataType>  
class base {
virtual DataType* getPtr() = 0;
//...
};

and


class derivedAType : public base<int>

But this changes base class to a template class which means you cant store them together, base<int> is different from base<short>


If this isnt acceptable, the other options is just a tad bit cleaner than your code but abt the same, refer to this question. Basically derived class return types can reflect their true type and i think it should get automatically converted to void*, so you dont have to manually cast the pointer.



Not sure about your problem. But maybe a double callback can help:


class Callback {
public:
virtual void do_int( int i ) const = 0;
virtual void do_short( short s ) const = 0;
/* ... */
}

class base {
public:
virtual void do_stuff(const Callback & c); /* will need a more telling name */
virtual ~base() {};
};

class derivedAType : public base {
protected:
int _i;
public:
derivedAType(int i): _i(0) { _i = i; };
virtual ~derivedAType() {}

virtual void do_stuff(const Callback & c) {
c.do_int( _i );
}
};

class derivedBType : public base {
protected:
short _s;
public:
derivedBType(short s): _s(0) { _s = s; };
virtual ~derivedBType() {}

virtual void do_stuff( const Callback & c) {
c.do_short( _s );
}
};

class print_callback : public Callback {
public:
virtual void do_int( int i ) const { std::cout << i; }
virtual void do_short( short s ) const { std::cout << s; }
}

int main() {
base *b1 = new derivedAType(1203912);
base *b2 = new derivedBType(25273);



std::cout << "b1 : ";
b1->do_stuff(print_callback());
std::cout << "\nb2 : ";
b2->do_stuff(print_callback());
std::cout << std::endl;

delete b2;
delete b1;

return 0;
}

Of course you can simplify this by just storing the created print callback, and using it twice.


0 commentaires:

Enregistrer un commentaire