S
Sensei
I was philosophizing on inheritance in C++, and I was wondering this.
Bear with me, as this is something more of a philosophy/history, rather
than a technical one.
What would be a use case for non virtual members in a class hierarchy?
class Base
{
public:
virtual void hello() { std::cout << "Base" << std::endl; }:
}
class Derived : public Base
{
public:
virtual void hello() { std::cout << "Derived" << std::endl; }:
}
Virtual allows me to use a Base class, and yet call the right function
hello().
Base *b = new Base;
Base *d = new Derived;
b->hello();
d->hello();
Now, if I let virtual out from Base and Derived, I will "slice" the
derived class, and d->hello() will print, "Base".
Why is a member function non-virtual by default, even from an
historically accurate point of view?
From a user point of view, the "slicing" is an "error", or an
unexpected behavior, to say the least. Having a base class pointer is
useful, and it will call the right derived class when needed.
Not only that, but choosing non-virtual as the default behavior, means
that virtual is quite "extravagant", and therefore needs to be added by
hand. But, at least in my experience, virtual is a given, and
non-virtual is the exception.
I'd really like to understand the rationale behind this choice, with a
use case that makes sense from an operational point of view, and not
just as an academic exercise.
This question bugged me when I tried to make only Derived non-virtual,
and subclassing it.
class Base
{
public:
virtual void hello() { std::cout << "Base" << std::endl; };
};
class Derived : public Base
{
public:
void hello() { std::cout << "Derived" << std::endl; };
};
class Last : public Derived
{
public:
void hello() { std::cout << "Last" << std::endl; };
};
At least on my system (Apple clang version 4.1 x86_64-apple-darwin12.2.0
Thread model: posix), it seems that "virtual" survives:
Base *b = new Base;
Base *d = new Derived;
Base *l = new Last;
b->hello();
d->hello();
l->hello();
% clang++ a.cpp && ./a.out
clang++ a.cpp && ./a.out
Base
Derived
Last
Is this the correct behavior? Why is this?
Thanks!!
Bear with me, as this is something more of a philosophy/history, rather
than a technical one.
What would be a use case for non virtual members in a class hierarchy?
class Base
{
public:
virtual void hello() { std::cout << "Base" << std::endl; }:
}
class Derived : public Base
{
public:
virtual void hello() { std::cout << "Derived" << std::endl; }:
}
Virtual allows me to use a Base class, and yet call the right function
hello().
Base *b = new Base;
Base *d = new Derived;
b->hello();
d->hello();
Now, if I let virtual out from Base and Derived, I will "slice" the
derived class, and d->hello() will print, "Base".
Why is a member function non-virtual by default, even from an
historically accurate point of view?
From a user point of view, the "slicing" is an "error", or an
unexpected behavior, to say the least. Having a base class pointer is
useful, and it will call the right derived class when needed.
Not only that, but choosing non-virtual as the default behavior, means
that virtual is quite "extravagant", and therefore needs to be added by
hand. But, at least in my experience, virtual is a given, and
non-virtual is the exception.
I'd really like to understand the rationale behind this choice, with a
use case that makes sense from an operational point of view, and not
just as an academic exercise.
This question bugged me when I tried to make only Derived non-virtual,
and subclassing it.
class Base
{
public:
virtual void hello() { std::cout << "Base" << std::endl; };
};
class Derived : public Base
{
public:
void hello() { std::cout << "Derived" << std::endl; };
};
class Last : public Derived
{
public:
void hello() { std::cout << "Last" << std::endl; };
};
At least on my system (Apple clang version 4.1 x86_64-apple-darwin12.2.0
Thread model: posix), it seems that "virtual" survives:
Base *b = new Base;
Base *d = new Derived;
Base *l = new Last;
b->hello();
d->hello();
l->hello();
% clang++ a.cpp && ./a.out
clang++ a.cpp && ./a.out
Base
Derived
Last
Is this the correct behavior? Why is this?
Thanks!!