base classes and inheritance problem

Z

zionztp

Hello, considering this code:

class A {
protected:
int n;
};

class B : public A {
public:
void setn(int k){ n = k;}
};

int main()
{
A *c;
c = new B();
c->setn(10);

return 0;
}

This of course will not compile, i'm trying to avoid using virtual
functions in class A and i was wondering if there exist a way of
achieving something like this code.
 
A

Alf P. Steinbach

* (e-mail address removed):
Hello, considering this code:

class A {
protected:
int n;
};

class B : public A {
public:
void setn(int k){ n = k;}
};

int main()
{
A *c;
c = new B();
c->setn(10);

return 0;
}

This of course will not compile, i'm trying to avoid using virtual
functions in class A and i was wondering if there exist a way of
achieving something like this code.

Since you're wondering about that, and also since you're considering leaving a
data member uninitialized for some time, and also since you're considering a
setter function for that data member, chances are near 100% that you're
relatively (understatement) new to the language and have embarked on a journey
of Evil Premature Optimization, which, if you continue, will lead to much grief.

What do your measurements say about the impact of virtual functions?

Aha, no measurements!

Well, there you are, it's a case of severe, evil premature optimization.

Here's one way to do things more properly:

class A
{
private:
int myN;
public:
A( int n ): myN( n ) {}
int n() const { return myN; }
};

class B: public A
{
public:
B( int n ): A( n ) {}
};

int main()
{
B c; // And yes, that's it, all you have to do.
}


Cheers, & hth.,

- Alf
 
Z

zionztp

* (e-mail address removed):









Since you're wondering about that, and also since you're considering leaving a
data member uninitialized for some time, and also since you're considering a
setter function for that data member, chances are near 100% that you're
relatively (understatement) new to the language and have embarked on a journey
of Evil Premature Optimization, which, if you continue, will lead to much grief.

What do your measurements say about the impact of virtual functions?

Aha, no measurements!

Well, there you are, it's a case of severe, evil premature optimization.

Here's one way to do things more properly:

class A
{
private:
int myN;
public:
A( int n ): myN( n ) {}
int n() const { return myN; }
};

class B: public A
{
public:
B( int n ): A( n ) {}
};

int main()
{
B c; // And yes, that's it, all you have to do.
}

Cheers, & hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?


Thanks for your reply, well my example was pretty bad (both code and
as example), so i will try with another:

#include <iostream>
using namespace std;

class A
{
public:
A(){n=5;}
virtual void show() = 0;

protected:
int n;
};

class B : public A
{
public:
void show(){cout << n << endl;}
};

class C : public A
{
public:
void show(){cout << n*2 << endl;}
};

int main()
{
A *c;
int class_num = 0; //user input

if(class_num == 0){
c = new B();
}else{
c = new C();
}

c->show();

delete c;
return 0;
}

Considering this example, what would be the best way if i wanted to
avoid virtual functions? of course i've reconsidered the use of
virtual functions since it may be totally unneeded optimization to
avoid them, but im just curious about this right now, and yes you are
right im not very used to C++ i mainly use it as an "extended" C.
 
P

Paavo Helde

(e-mail address removed) wrote in (e-mail address removed):
Hello, considering this code:

class A {
protected:
int n;
};

class B : public A {
public:
void setn(int k){ n = k;}
};

int main()
{
A *c;
c = new B();
c->setn(10);

return 0;
}

This of course will not compile, i'm trying to avoid using virtual
functions in class A and i was wondering if there exist a way of
achieving something like this code.

First give us sound reasons why you are trying to avoid virtual
functions. Virtual functions are designed for discriminating classes at
run-time, if you don't use this mechanism you have to discriminate them
by other means, which will become much more messy.

hth
Paavo
 
A

Alf P. Steinbach

* (e-mail address removed):
#include <iostream>
using namespace std;

class A
{
public:
A(){n=5;}
virtual void show() = 0;

protected:
int n;
};

class B : public A
{
public:
void show(){cout << n << endl;}
};

class C : public A
{
public:
void show(){cout << n*2 << endl;}
};

int main()
{
A *c;
int class_num = 0; //user input

if(class_num == 0){
c = new B();
}else{
c = new C();
}

c->show();

delete c;
return 0;
}

Considering this example, what would be the best way if i wanted to
avoid virtual functions? of course i've reconsidered the use of
virtual functions since it may be totally unneeded optimization to
avoid them, but im just curious about this right now, and yes you are
right im not very used to C++ i mainly use it as an "extended" C.

Please don't quote signatures.

Depending on what it is you want to try to achieve...

int main()
{
using namespace std;

int const userInput = 0;
cout << (userInput == 0? 5 : 10) << endl;
}

You might think that answer's facetious. But it's not. If the problem doesn't
call for classes and objects, or templates, whatever..., don't. Use the tools
and abstractions that suit the problem. Give a damn about micro-optimization.
Aim at clarity.


Cheers, & hth.,

- Alf
 
G

Greg Herlihy

* (e-mail address removed):









Since you're wondering about that, and also since you're considering leaving a
data member uninitialized for some time, and also since you're considering a
setter function for that data member, chances are near 100% that you're
relatively (understatement) new to the language and have embarked on a journey
of Evil Premature Optimization, which, if you continue, will lead to much grief.

What do your measurements say about the impact of virtual functions?

Aha, no measurements!

Well, there you are, it's a case of severe, evil premature optimization.

Here's one way to do things more properly:

   class A
   {
   private:
       int myN;
   public:
       A( int n ): myN( n ) {}
       int n() const { return myN; }
   };

   class B: public A
   {
   public:
       B( int n ): A( n ) {}
   };

   int main()
   {
       B c;    // And yes, that's it, all you have to do.
   }

In the above program, "B" objects cannot be default-constructed, so
"c"'s declaration will not compile. Possible solutions include:
initializing "c" with an int value:

B c(-3);

or, providing a default argument to B's constructor:

B( int n = 5): A( n ) {}

Greg
 
B

Bo Persson

class C : public A
{
public:
void show(){cout << n*2 << endl;}
};

int main()
{
A *c;
int class_num = 0; //user input

if(class_num == 0){
c = new B();
}else{
c = new C();
}

c->show();

delete c;
return 0;
}

Considering this example, what would be the best way if i wanted to
avoid virtual functions? of course i've reconsidered the use of
virtual functions since it may be totally unneeded optimization to
avoid them, but im just curious about this right now, and yes you
are right im not very used to C++ i mainly use it as an "extended"
C.

And we ask ourselves: WHY do you want to avoid making this particular
function virtual? If you can afford calls to new, virtual functions
are cheap in comparison.


If you look into the implementation of cout operations, you will
probably be amazed over the number of virtual functions that involves.


Bo Persson
 
Z

zionztp

Thank you all for your replies, i will tell you a little of what i'm
trying to do so maybe you can understand why im asking this, im
working in a simple 2d graphic rendering engine, the "drawing" class
will have many functions and i wanted to implement these functions
using different APIs like something like:

N *c;
c = new A();
if(change){
delete c;
c = new B();
}
delete c;

And since some functions are called many times i was a bit worried
about a possible slowdown caused by virtual functions.
 
T

thomas

Thank you all for your replies, i will tell you a little of what i'm
trying to do so maybe you can understand why im asking this, im
working in a simple 2d graphic rendering engine, the "drawing" class
will have many functions and i wanted to implement these functions
using different APIs like something like:

N *c;
c = new A();
if(change){
    delete c;
    c = new B();}

delete c;

And since some functions are called many times i was a bit worried
about a possible slowdown caused by virtual functions.

I don't think virtual function will bring you an effciency problem.
The virtual pointer will be changed to an entry index in vtable.
Calling virtual function is like calling other functions, which will
bring no overhead.
 
J

Jerry Coffin

Thank you all for your replies, i will tell you a little of what i'm
trying to do so maybe you can understand why im asking this, im
working in a simple 2d graphic rendering engine, the "drawing" class
will have many functions and i wanted to implement these functions
using different APIs like something like:

N *c;
c = new A();
if(change){
delete c;
c = new B();
}
delete c;

And since some functions are called many times i was a bit worried
about a possible slowdown caused by virtual functions.

First, I'd note that I don't find your explanation particularly
revelatory -- you've said a bit about what you're doing right now, but
nothing about _why_ you're doing it. We can't suggest better ways of
doing what you want until we know what you want.

One thing that was pointed out previously in this thread remains though:
the cost of virtual a function call over a normal function call is
typically going to be something like a nanosecond. The cost of a new or
delete is typically going to be at least a microsecond (i.e. 1000 times
longer) and can easily run into the millisecond range (i.e. a million
times longer).

IOW, when you're using new or delete, adding or removing a virtual
function call is likely to affect speed by well under 1%, and quite
possibly not even by enough to measure.
 
P

Paavo Helde

(e-mail address removed) wrote in

[...]
Thanks for your reply, well my example was pretty bad (both code and
as example), so i will try with another:

#include <iostream>
using namespace std;

class A
{
public:
A(){n=5;}
virtual void show() = 0;

protected:
int n;
};

class B : public A
{
public:
void show(){cout << n << endl;}
};

class C : public A
{
public:
void show(){cout << n*2 << endl;}
};

int main()
{
A *c;
int class_num = 0; //user input

if(class_num == 0){
c = new B();
}else{
c = new C();
}

c->show();

delete c;
return 0;
}

Considering this example, what would be the best way if i wanted to
avoid virtual functions? of course i've reconsidered the use of
virtual functions since it may be totally unneeded optimization to
avoid them, but im just curious about this right now, and yes you are
right im not very used to C++ i mainly use it as an "extended" C.

Since you asked, and since you are curious - don't use the examples below
in real work!

Way 1:

B* try_b = dynamic_cast<B*>(c);
if (try_b) {
try_b->B::show();
} else {
static_cast<C*>(c)->C::show();
}

Here you still need at least one virtual function in A class for
dynamic_cast to work. The explicit B::show() and C::show are for avoiding
virtual call in case A::show() is virtual, it it's not, the class names
can be dropped.

Note that this is more ugly and more cumbersome than virtual function
calls. Also, dynamic_cast might well be slower than virtual dispatch,
unless you can haul it out of a tight loop.

Way 2:

class A {
public:
int type_;
// ... rest of A as in your example
};

class B: public A {
public:
B() {type_=1;}
// ...
};

class C: public A {
public:
C() {type_=2;}
// ...
};

// ...

A *c = ... // new B or C

switch(c->type_) {
case 1:
static_cast<B*>(c)->B::show();
break;
case 2:
static_cast<C*>(c)->C::show();
break;
}

(The same here: if the show function is not virtual, the class prefixes
in function names can be dropped. The switch might well be not faster
than the virtual function call, unless you can haul the switch out of a
tight loop.)

Way 3:

#include <iostream>

class A {
public:
void (*show_ptr_)(A*);
A(): n_(5) {}
int n_;
};

void show_B(A* a) {
std::cout << a->n_ << "\n";
}

class B: public A {
public:
B() { show_ptr_ = show_B; }
};


void show_C(A* a) {
std::cout << 2*a->n_ << "\n";
}

class C: public A {
public:
C() { show_ptr_ = show_C; }
};

int main() {
A *c = new C();
(*c->show_ptr_)(c);
}


This is emulating the virtual dispatch and most probably having the same
or worse performance. Hauling the decision out of the loop is not really
possible here. This approach is sometimes used in C language for
emulating C++ virtual methods.

hth
Paavo
 
Z

zionztp

Since you asked, and since you are curious - don't use the examples below
in real work!

Way 1:

B* try_b = dynamic_cast<B*>(c);
if (try_b) {
try_b->B::show();} else {

static_cast<C*>(c)->C::show();

}

Here you still need at least one virtual function in A class for
dynamic_cast to work. The explicit B::show() and C::show are for avoiding
virtual call in case A::show() is virtual, it it's not, the class names
can be dropped.

Note that this is more ugly and more cumbersome than virtual function
calls. Also, dynamic_cast might well be slower than virtual dispatch,
unless you can haul it out of a tight loop.

Way 2:

class A {
public:
int type_;
// ... rest of A as in your example

};

class B: public A {
public:
B() {type_=1;}
// ...

};

class C: public A {
public:
C() {type_=2;}
// ...

};

// ...

A *c = ... // new B or C

switch(c->type_) {
case 1:
static_cast<B*>(c)->B::show();
break;
case 2:
static_cast<C*>(c)->C::show();
break;

}

(The same here: if the show function is not virtual, the class prefixes
in function names can be dropped. The switch might well be not faster
than the virtual function call, unless you can haul the switch out of a
tight loop.)

Way 3:

#include <iostream>

class A {
public:
void (*show_ptr_)(A*);
A(): n_(5) {}
int n_;

};

void show_B(A* a) {
std::cout << a->n_ << "\n";

}

class B: public A {
public:
B() { show_ptr_ = show_B; }

};

void show_C(A* a) {
std::cout << 2*a->n_ << "\n";

}

class C: public A {
public:
C() { show_ptr_ = show_C; }

};

int main() {
A *c = new C();
(*c->show_ptr_)(c);

}

This is emulating the virtual dispatch and most probably having the same
or worse performance. Hauling the decision out of the loop is not really
possible here. This approach is sometimes used in C language for
emulating C++ virtual methods.

hth
Paavo

Thanks a lot!, and don't worry i can understand this is not correct
and that it should be avoided, i would call this a "hack" :p.
 
P

Paavo Helde

(e-mail address removed) wrote in

Thanks a lot!, and don't worry i can understand this is not correct
and that it should be avoided, i would call this a "hack" :p.

You are welcome! I was not so worried about you, but about the other
regular posters who would post an avalanche of warnings about avoiding such
kind of coding style.

There are always exceptions - if the performance really hurts because of
calling the virtual function in a tight loop, then one has to take the
virtual dispatching part out of the loop somehow (or better, enhance the
design so that virtual functions are not called in tight loops). However,
the compiler optimizations and hardware control flow predictions become
better all the time so this kind of "hack" might not buy you anything at
all quite soon.

rgaerds
Paavo
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top