为什么 C++ 允许私有父类的指针多态性?
Why does C++ allow this pointer polymorphism of private parent?
如果我从一个基 class 中私下继承一个派生的 class,我就无法获得 inhritetted class 的多态性。
但是我可以在派生的class中得到'this'指针的多态性。
我很好奇为什么 'this' 指针允许多态到其私有父级,但是 class 之外的指针却不允许。
提前致谢!
#include <iostream>
class Shape
{
public:
virtual void say() const = 0;
virtual void who()
{
std::cout << "Shape" << std::endl;
}
void whoAmI() {
this->who();
}
};
class Squire : private Shape
{
public:
virtual void say() const
{
std::cout << "Squire" << std::endl;
}
void doSay()
{
// why this pointer to Shape type is allowed in class?
privateSay(this);
}
private:
void privateSay(Shape* s)
{
s->say();
}
};
void say(Shape* s)
{
s->say();
}
int main(int argc, const char * argv[]) {
// insert code here...
Squire* s = new Squire();
// allowed
s->doSay();
// not allowd, compile errors
// Cannot cast 'Squire' to its private base class 'Shape'
say(s);
return 0;
}
=========
编辑澄清。
感谢所有的答案。
为了澄清我的问题,我认为如果 C++ 允许这种行为,它可能会稍微违反 encapsulation。
更清晰的案例:
#include <iostream>
class Base
{
public:
void baseFunc() const
{
std::cout << "baseFunc" << std::endl;
}
};
class Worker
{
public:
Worker(Base *pBase)
{
base_ = pBase;
}
void breakFunc() const
{
base_->baseFunc();
}
private:
Base *base_;
};
class Derived : private Base
{
public:
void init()
{
worker_ = new Worker(this);
}
Worker* getWorker()
{
return worker_;
}
private:
Worker *worker_;
};
int main()
{
Derived derived;
derived.init();
Worker *worker = derived.getWorker();
worker->breakFunc();
}
Baseclass的对象只作为父对象部分存在于Derivedclass的对象中,但是Derivedclass继承Baseclassprivately,意思是Derived的对象classhas-an Base的对象class,私下.
上面的代码违反了Derivedclass的封装规则,但是在编译过程中甚至没有给出警告。
在我看来,这种情况下应该使用显式强制转换,或者在编译时给出警告。
私有继承意味着来自基础 class 的 public
和 protected
符号成为派生 class 的 private
符号。 private
基础 class 的符号无法被派生 class 访问。仍然可以覆盖的私有虚拟方法除外。
this
指针,或者一般的 Class* ptr
在 class 内部使用,可以访问 class.
的私有字段
由于符号 Shape::say
在 Shape
中是 public,它在 Squire
中变为私有(顺便说一句,你是说 Square 吗?)。这会阻止 public 使用它,但不会被 this
使用。由于虚拟规则,这将“私有化”整个重写方法链。
void Squire::privateSay(Shape* s)
{
// Works because `Shape::say` is a public symbol of Shape -> private symbol of Squire and `this` can access private symbols.
s->say();
}
void say(Shape* s)
{
// Shape::say is a private symbol, obviously cannot be called.
s->say();
}
如果存在私有 Shape::foo()
方法,即使在 Squire
的任何方法中通过 this
也无法访问它。
这里问的问题是为什么基class在私有继承时可以访问。
答案很简单:因为基础 classes 总是对继承可见,无论继承类型如何。
当碱基在上下文中可见时,您可以 static_cast
到碱基 class。
class base
{
};
class inherited : base
{
public:
void foo()
{
// works, base is visible within the method.
auto pBase = static_cast<base*>(this);
}
};
int main() {
inherited i{};
// auto pBase = static_cast<base*>(&i); // won't compile, base is not visible
return 0;
}
如果我从一个基 class 中私下继承一个派生的 class,我就无法获得 inhritetted class 的多态性。
但是我可以在派生的class中得到'this'指针的多态性。
我很好奇为什么 'this' 指针允许多态到其私有父级,但是 class 之外的指针却不允许。
提前致谢!
#include <iostream>
class Shape
{
public:
virtual void say() const = 0;
virtual void who()
{
std::cout << "Shape" << std::endl;
}
void whoAmI() {
this->who();
}
};
class Squire : private Shape
{
public:
virtual void say() const
{
std::cout << "Squire" << std::endl;
}
void doSay()
{
// why this pointer to Shape type is allowed in class?
privateSay(this);
}
private:
void privateSay(Shape* s)
{
s->say();
}
};
void say(Shape* s)
{
s->say();
}
int main(int argc, const char * argv[]) {
// insert code here...
Squire* s = new Squire();
// allowed
s->doSay();
// not allowd, compile errors
// Cannot cast 'Squire' to its private base class 'Shape'
say(s);
return 0;
}
=========
编辑澄清。 感谢所有的答案。 为了澄清我的问题,我认为如果 C++ 允许这种行为,它可能会稍微违反 encapsulation。
更清晰的案例:
#include <iostream>
class Base
{
public:
void baseFunc() const
{
std::cout << "baseFunc" << std::endl;
}
};
class Worker
{
public:
Worker(Base *pBase)
{
base_ = pBase;
}
void breakFunc() const
{
base_->baseFunc();
}
private:
Base *base_;
};
class Derived : private Base
{
public:
void init()
{
worker_ = new Worker(this);
}
Worker* getWorker()
{
return worker_;
}
private:
Worker *worker_;
};
int main()
{
Derived derived;
derived.init();
Worker *worker = derived.getWorker();
worker->breakFunc();
}
Baseclass的对象只作为父对象部分存在于Derivedclass的对象中,但是Derivedclass继承Baseclassprivately,意思是Derived的对象classhas-an Base的对象class,私下.
上面的代码违反了Derivedclass的封装规则,但是在编译过程中甚至没有给出警告。
在我看来,这种情况下应该使用显式强制转换,或者在编译时给出警告。
私有继承意味着来自基础 class 的 public
和 protected
符号成为派生 class 的 private
符号。 private
基础 class 的符号无法被派生 class 访问。仍然可以覆盖的私有虚拟方法除外。
this
指针,或者一般的 Class* ptr
在 class 内部使用,可以访问 class.
由于符号 Shape::say
在 Shape
中是 public,它在 Squire
中变为私有(顺便说一句,你是说 Square 吗?)。这会阻止 public 使用它,但不会被 this
使用。由于虚拟规则,这将“私有化”整个重写方法链。
void Squire::privateSay(Shape* s)
{
// Works because `Shape::say` is a public symbol of Shape -> private symbol of Squire and `this` can access private symbols.
s->say();
}
void say(Shape* s)
{
// Shape::say is a private symbol, obviously cannot be called.
s->say();
}
如果存在私有 Shape::foo()
方法,即使在 Squire
的任何方法中通过 this
也无法访问它。
这里问的问题是为什么基class在私有继承时可以访问。
答案很简单:因为基础 classes 总是对继承可见,无论继承类型如何。
当碱基在上下文中可见时,您可以 static_cast
到碱基 class。
class base
{
};
class inherited : base
{
public:
void foo()
{
// works, base is visible within the method.
auto pBase = static_cast<base*>(this);
}
};
int main() {
inherited i{};
// auto pBase = static_cast<base*>(&i); // won't compile, base is not visible
return 0;
}