试图在 C++ 中调用子 class 中父 class 的受保护函数
trying to call protected function of parent class in child class in c++
我一直以为我懂继承,但显然我不懂。我想从子 class 调用同一父 class 的另一个实例的受保护成员函数,如以下示例代码所示:
#include <iostream>
class Parent {
protected:
void doStuff(){
std::cout << 5 << std::endl;
}
};
class Child : public Parent {
public:
void pubfunc(Parent* p){
p->doStuff();
}
};
int main(){
Child* c = new Child();
Parent* p = new Parent();
c->pubfunc(p);
return 0;
}
但是,此代码的编译失败并显示:
In member function ‘void Child::pubfunc(Parent*)’:
error: ‘void Parent::doStuff()’ is protected
error: within this context
我不想让 Child
class 成为 Parent
class 的 friend
以避免前向声明和前向包含子项class尽可能多。另外,我不想做 doStuff
public,因为在错误的情况下使用它真的会弄乱 Parent
的内部结构。
为什么会出现这个错误,最优雅的解决方法是什么?
class Parent
{
protected:
virtual void doStuff()
{
std::cout << 5 << std::endl;
}
};
class Child : public Parent
{
protected:
void doStuff() override
{
std::cout << 8 << std::endl;
}
public:
void pubfunc(Parent* p)
{
((Child*)p)->doStuff();
}
};
int main()
{
Child* c = new Child();
Parent* p = new Parent();
c->pubfunc(p); // will print 5
c->pubfunc(c); // will print 8
return 0;
}
受保护的成员可以在定义它们的 class 和从 class 继承的 class 中访问。有时,当人们看到这种错误时,它会让人感到困惑。但实际上你为父对象调用了 doStuff 函数,如果函数调用在继承 class 内完成,它不会计量。如果您从 main() 调用 doStuff 函数,结果将是相同的。
主要问题在于,如果 C++ 允许您直接访问基 class 指针所指对象的非 public 成员,那么您可以轻松访问简单地通过从公共基础派生对象。
这仍然是 C++ 类型系统中的一个已知 漏洞 ,如下所示,您无需修改基 class 即可获得该访问权限,并且无需使用强制转换或类似的东西。
在第三个抓手上,你应该做的是直接在基class中支持预期的用法,通过在那里添加一个static
成员函数,如下:
#include <iostream>
using namespace std;
class Base
{
protected:
void doStuff()
{
cout << 5 << endl;
}
static void doStuff( Base* p ) { p->doStuff(); }
};
class Derived : public Base
{
public:
void pubfunc( Base* p )
{
doStuff( p );
}
};
auto main() -> int
{
Derived d;
Base b;
d.pubfunc( &b );
}
以我的愚见,这是最清晰和优雅的。
但为了完整性,类型系统漏洞:
#include <iostream>
using namespace std;
class Base
{
protected:
void doStuff()
{
cout << 5 << endl;
}
};
class Derived : public Base
{
public:
void pubfunc( Base* p )
{
(p->*&Derived::doStuff)();
}
};
auto main() -> int
{
Derived d;
Base b;
d.pubfunc( &b );
}
不过我推荐 static
成员函数。
我一直以为我懂继承,但显然我不懂。我想从子 class 调用同一父 class 的另一个实例的受保护成员函数,如以下示例代码所示:
#include <iostream>
class Parent {
protected:
void doStuff(){
std::cout << 5 << std::endl;
}
};
class Child : public Parent {
public:
void pubfunc(Parent* p){
p->doStuff();
}
};
int main(){
Child* c = new Child();
Parent* p = new Parent();
c->pubfunc(p);
return 0;
}
但是,此代码的编译失败并显示:
In member function ‘void Child::pubfunc(Parent*)’:
error: ‘void Parent::doStuff()’ is protected
error: within this context
我不想让 Child
class 成为 Parent
class 的 friend
以避免前向声明和前向包含子项class尽可能多。另外,我不想做 doStuff
public,因为在错误的情况下使用它真的会弄乱 Parent
的内部结构。
为什么会出现这个错误,最优雅的解决方法是什么?
class Parent
{
protected:
virtual void doStuff()
{
std::cout << 5 << std::endl;
}
};
class Child : public Parent
{
protected:
void doStuff() override
{
std::cout << 8 << std::endl;
}
public:
void pubfunc(Parent* p)
{
((Child*)p)->doStuff();
}
};
int main()
{
Child* c = new Child();
Parent* p = new Parent();
c->pubfunc(p); // will print 5
c->pubfunc(c); // will print 8
return 0;
}
受保护的成员可以在定义它们的 class 和从 class 继承的 class 中访问。有时,当人们看到这种错误时,它会让人感到困惑。但实际上你为父对象调用了 doStuff 函数,如果函数调用在继承 class 内完成,它不会计量。如果您从 main() 调用 doStuff 函数,结果将是相同的。
主要问题在于,如果 C++ 允许您直接访问基 class 指针所指对象的非 public 成员,那么您可以轻松访问简单地通过从公共基础派生对象。
这仍然是 C++ 类型系统中的一个已知 漏洞 ,如下所示,您无需修改基 class 即可获得该访问权限,并且无需使用强制转换或类似的东西。
在第三个抓手上,你应该做的是直接在基class中支持预期的用法,通过在那里添加一个static
成员函数,如下:
#include <iostream>
using namespace std;
class Base
{
protected:
void doStuff()
{
cout << 5 << endl;
}
static void doStuff( Base* p ) { p->doStuff(); }
};
class Derived : public Base
{
public:
void pubfunc( Base* p )
{
doStuff( p );
}
};
auto main() -> int
{
Derived d;
Base b;
d.pubfunc( &b );
}
以我的愚见,这是最清晰和优雅的。
但为了完整性,类型系统漏洞:
#include <iostream>
using namespace std;
class Base
{
protected:
void doStuff()
{
cout << 5 << endl;
}
};
class Derived : public Base
{
public:
void pubfunc( Base* p )
{
(p->*&Derived::doStuff)();
}
};
auto main() -> int
{
Derived d;
Base b;
d.pubfunc( &b );
}
不过我推荐 static
成员函数。