Pure virtual accessors?

A

ardi

Hi,

In order to automate the document management in my applications (or at least minimizing the coding effort), I'm planning to base the document design on an abstract class which has a pure virtual getter, a pure virtual setter,a pure virtual function for saving the item into a file, a pure virtual function for reading it from the file, as well as any other helpful functions(such as automatically flagging the document as "dirty" when the value has changed by calling the setter).

So, then I'd derive this abstract class into (for example) different classes for 16bit signed integers, 32bit unsigned integers, 32 bit floating point, 64 bit floating point, etc...

The pure virtual functions for file I/O are trivial, and have no secrets.

....but... the pure virtual accessors are a different matter...

I mean: how do you write a pure virtual getter if the return value has a different data type for each derived class?

The getter for the 32 bit unsigned int will have a 32bit unsigned int as return value.

The getter for the 32 bit float, will return a 32 bit float.

How would I define both getters from a pure virtual getter? Is it possible?

Thanks a lot for any suggestions, because this abstract data type class would ease a lot the coding effort in my applications!!

ardi
 
S

Stefan Ram

ardi said:
I mean: how do you write a pure virtual getter if the return value has a different data type for each derived class?
The getter for the 32 bit unsigned int will have a 32bit unsigned int as return value.

I can write this with /pointers/, but not with the actual values.

struct base { };

struct intval : base { int i; };
struct doubleval : base { double x; };

struct getter{ virtual base * get() const = 0; };

struct intgetter : getter
{ intval * get() const override { return new intval; }; };

struct doublegetter : getter
{ doubleval * get() const override { return new doubleval; }; };
 
M

Marcel Müller

I mean: how do you write a pure virtual getter if the return value has a different data type for each derived class?

The getter for the 32 bit unsigned int will have a 32bit unsigned int as return value.

The getter for the 32 bit float, will return a 32 bit float.

How would I define both getters from a pure virtual getter? Is it possible?

No. But it makes no sense anyway. If any part of the application uses
the abstract base (without knowing about the actual implementation), it
cannot extract a value of an unknown type, because it simply cannot have
a target of the appropriate type.

It seems that you want to mix design time polymorphism (here templates)
with runtime polymorphism (virtual functions).

More details about what you intend to do with the abstract getters would
be helpful.


Marcel
 
S

Stefan Ram

Marcel Müller said:
No. But it makes no sense anyway. If any part of the application uses
the abstract base (without knowing about the actual implementation), it
cannot extract a value of an unknown type

Extracting values is for procedural programming,
objects accept messages.

#include <iostream>
#include <ostream>

struct val { virtual void print() const = 0; };

struct intval : val
{ int i = 5; void print() const override{ ::std::cout << i << '\n'; }};

struct doubleval : val
{ int x = 7; void print() const override{ ::std::cout << x << '\n'; }};

struct getter{ virtual val * get() const = 0; };

struct intgetter : getter
{ intval * get() const override { return new intval; }; };

struct doublegetter : getter
{ doubleval * get() const override { return new doubleval; }; };

int main()
{ getter * ig = new intgetter;
getter * dg = new doublegetter;
ig->get()->print();
dg->get()->print(); }
 
H

Haochen Xie

I guess boost.variant could help you? You can make the return type a
variant, and that sounds like what you want.

Or you could make your own using union holding pointers to various
types, and provide different accessors for all the type it supports. An
example could be:


#include <string>
#include <typeinfo>

struct Variant {
union {
int *_i;
float *_f;
std::string *_str;
};

enum {
vt_int, vt_float, vt_string
} type;

Variant(int x)
: _i(new int(x)), type(vt_int) {}
Variant(float x)
: _f(new float(x)), type(vt_float) {}
Variant(std::string x)
: _str(new std::string(x)), type(vt_string) {}
int &get_int() {
if(type == vt_int)
return *_i;
else
throw std::bad_cast();
}
float &get_float() {
if(type == vt_float)
return *_f;
else
throw std::bad_cast();
}
std::string &get_string() {
if(type == vt_string)
return *_str;
else
throw std::bad_cast();
}
};


For testing program:


#include <cassert>
#include <iostream>
using namespace std;

int main() {
Variant v1(17), v2((float)25.8), v3("I'm a string");

assert(v1.type == Variant::vt_int);
assert(v2.type == Variant::vt_float);
assert(v3.type == Variant::vt_string);

cout << v1.get_int() << endl;
cout << v2.get_float() << endl;
cout << v3.get_string() << endl;

// The following line will throw a bad_cast exception
cout << v1.get_string() << endl;
}


Virtual functions in a hierarchy tree must have *exactly* the same
signature and return type if you want them to work correctly.
 
A

ardi

No. But it makes no sense anyway. If any part of the application uses

the abstract base (without knowing about the actual implementation), it

cannot extract a value of an unknown type, because it simply cannot have

a target of the appropriate type.



It seems that you want to mix design time polymorphism (here templates)

with runtime polymorphism (virtual functions).



More details about what you intend to do with the abstract getters would

be helpful.





Marcel

First, thanks a lot to all who replied. Your ideas were helpful.

Second, you're right. My idea was wrong in the first place. What I'm doing is a class hierarchy where data and the document is managed as automatically as possible. Imagine you want to enhance a program adding a new member toa class. Typically this implies adding new logic in several places of the class even when the new member has a trivial management. My goal is that adding new members requires as few lines of code as possible.

But, anyway, back to the point, I realized I don't want nor need "pure virtual getters" in such a system, so you were right in your comment.

Thanks.

ardi
 

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,744
Messages
2,569,484
Members
44,905
Latest member
Kristy_Poole

Latest Threads

Top