Herb Sutter's famous article Virtuality, states the following:
Guideline #2: Prefer to make virtual functions private.
That's easy. This lets the derived classes override the function to customize the behavior as needed, without further exposing the virtual functions directly by making them callable by derived classes (as would be possible if the functions were just protected)
In the code below, the private_base_func() is private virtual function declared in the base class, and called in the drived class constructor, Strangely, this code compiles fine and it invokes a private virtual function of the base class from the drived class, which contradicts with the above statement. This is getting me very confused.
class base
{
public:
base() {}
virtual ~base(){}
private:
virtual void private_base_func()
{
std::cout << "Base Class invoke" << std::endl;
}
};
class drived : public base
{
public:
drived()
{
private_base_func(); // this line should not compile
}
private:
// Overriding base class virtual function
void private_base_func()
{
std::cout << "Drived class invoke" << std::endl;
}
};
int main()
{
base* ptr = new drived();
return 0;
}
Thanks in advances for your response
That's because you're calling drived
's version of private_base_func
, which is of course accessible within drived
. The function you can't call is base
's version:
drived()
{
base::private_base_func(); // this line will not compile
}
private_base_func(); // this line should not compile
How so? private_base_func
is a private
function in drived
and that line is inside drived
, so it is perfectly fine to call it. Note that this differs from:
drived()
{
base b;
b.private_base_func(); // this line does not compile
}
At any rate that is not what the article is about. The point of the article is that there are two different interfaces defined in the base class. One is the public interface, that offers the operations that users of your base need. The other is the set of virtual functions, which defines the operations that your extensions provide to your base class. By separating both interfaces you are decoupling your users from your providers and gaining flexibility.
Herb Sutter's famous article Virtuality, states the following:
Guideline #2: Prefer to make virtual functions private.
That's easy. This lets the derived classes override the function to customize the behavior as needed, without further exposing the virtual functions directly by making them callable by derived classes (as would be possible if the functions were just protected)
In the code below, the private_base_func() is private virtual function declared in the base class, and called in the drived class constructor, Strangely, this code compiles fine and it invokes a private virtual function of the base class from the drived class, which contradicts with the above statement. This is getting me very confused.
class base
{
public:
base() {}
virtual ~base(){}
private:
virtual void private_base_func()
{
std::cout << "Base Class invoke" << std::endl;
}
};
class drived : public base
{
public:
drived()
{
private_base_func(); // this line should not compile
}
private:
// Overriding base class virtual function
void private_base_func()
{
std::cout << "Drived class invoke" << std::endl;
}
};
int main()
{
base* ptr = new drived();
return 0;
}
Thanks in advances for your response
That's because you're calling drived
's version of private_base_func
, which is of course accessible within drived
. The function you can't call is base
's version:
drived()
{
base::private_base_func(); // this line will not compile
}
private_base_func(); // this line should not compile
How so? private_base_func
is a private
function in drived
and that line is inside drived
, so it is perfectly fine to call it. Note that this differs from:
drived()
{
base b;
b.private_base_func(); // this line does not compile
}
At any rate that is not what the article is about. The point of the article is that there are two different interfaces defined in the base class. One is the public interface, that offers the operations that users of your base need. The other is the set of virtual functions, which defines the operations that your extensions provide to your base class. By separating both interfaces you are decoupling your users from your providers and gaining flexibility.
0 commentaires:
Enregistrer un commentaire