使用虚函数访问私有函数
Accessing Private function using virtual function
如何避免使用基 class 虚函数间接调用私有函数。
class baseclass{
public:
virtual void printmynumber() = 0;
};
class derivedclass : public baseclass
{
private:
int m_mynumber;
void printmynumber()
{
cout << m_mynumber << endl;
}
public:
derivedclass(int n)
{
m_mynumber = n;
}
};
void main()
{
baseclass *bObj = new derivedclass(10);
bObj->printmynumber();
delete bObj;
}
如何避免私有函数的调用?
你不能。
void printmynumber()
是 baseclass
的 public API 的一部分,因此是 derivedclass
的一部分。如果您希望 derivedclass::printmynumber()
不是 public,也许 derivedclass
不应该继承自 baseclass
。
如评论中所建议,这违反了 Liskov substitution principle: the L in SOLID。
继承不能做到这一点。给定一个指向 baseclass
的指针,编译器只知道它有一个 public
virtual
函数,因此允许相应地调用该函数。
派生class已选择从基础class继承,并实现了具有不同访问权限的功能。但是其中 none 是可见的,只给出一个指向基数的指针。
没有什么可以阻止 derivedclass::printmynumber()
被实现为什么都不做 - 这意味着如果代码调用它,将不会有任何可观察到的效果(假设没有预期效果是可以容忍的)。
真正的解决方案是修复您的设计,而不是尝试解决其中的缺陷。不要从 baseclass
继承 derivedclass
。这样,根本无法调用 derivedclass
的成员函数,仅给出指向 baseclass
的指针,因为类型不相关(将 derivedclass *
传递给期望 baseclass *
通常会被诊断为错误)。
顺便说一句:main()
returns int
,而不是 void
。一些编译器支持 void main()
作为非标准扩展(并且其中一些编译器的文档错误地将这种东西描述为标准)但最好避免使用。
我能看到在不修改基础 class 的情况下阻止它的唯一方法是在原始基础 class 和最终派生的 class 之间添加另一个继承层].在那个中间 class 您将函数设为私有或删除。然后你使用指向中间 class 的指针作为基指针。
类似
class baseclass
{
public:
virtual void printmynumber() = 0;
};
struct middleclass : public baseclass
{
void printmynumber() = delete;
};
class derivedclass : public middleclass
{
private:
int m_mynumber;
void printmynumber()
{
cout << m_mynumber << endl;
}
public:
derivedclass(int n)
{
m_mynumber = n;
}
};
void main()
{
// Here use the middleclass instead of the baseclass
middleclass *bObj = new derivedclass(10);
// printmynumber is deleted in the middleclass and can't be called
// This will result in a build error
bObj->printmynumber();
delete bObj;
}
这当然需要修改所有使用原始基class的地方,但不需要修改基class本身。所以这是一个权衡。
如何避免使用基 class 虚函数间接调用私有函数。
class baseclass{
public:
virtual void printmynumber() = 0;
};
class derivedclass : public baseclass
{
private:
int m_mynumber;
void printmynumber()
{
cout << m_mynumber << endl;
}
public:
derivedclass(int n)
{
m_mynumber = n;
}
};
void main()
{
baseclass *bObj = new derivedclass(10);
bObj->printmynumber();
delete bObj;
}
如何避免私有函数的调用?
你不能。
void printmynumber()
是 baseclass
的 public API 的一部分,因此是 derivedclass
的一部分。如果您希望 derivedclass::printmynumber()
不是 public,也许 derivedclass
不应该继承自 baseclass
。
如评论中所建议,这违反了 Liskov substitution principle: the L in SOLID。
继承不能做到这一点。给定一个指向 baseclass
的指针,编译器只知道它有一个 public
virtual
函数,因此允许相应地调用该函数。
派生class已选择从基础class继承,并实现了具有不同访问权限的功能。但是其中 none 是可见的,只给出一个指向基数的指针。
没有什么可以阻止 derivedclass::printmynumber()
被实现为什么都不做 - 这意味着如果代码调用它,将不会有任何可观察到的效果(假设没有预期效果是可以容忍的)。
真正的解决方案是修复您的设计,而不是尝试解决其中的缺陷。不要从 baseclass
继承 derivedclass
。这样,根本无法调用 derivedclass
的成员函数,仅给出指向 baseclass
的指针,因为类型不相关(将 derivedclass *
传递给期望 baseclass *
通常会被诊断为错误)。
顺便说一句:main()
returns int
,而不是 void
。一些编译器支持 void main()
作为非标准扩展(并且其中一些编译器的文档错误地将这种东西描述为标准)但最好避免使用。
我能看到在不修改基础 class 的情况下阻止它的唯一方法是在原始基础 class 和最终派生的 class 之间添加另一个继承层].在那个中间 class 您将函数设为私有或删除。然后你使用指向中间 class 的指针作为基指针。
类似
class baseclass
{
public:
virtual void printmynumber() = 0;
};
struct middleclass : public baseclass
{
void printmynumber() = delete;
};
class derivedclass : public middleclass
{
private:
int m_mynumber;
void printmynumber()
{
cout << m_mynumber << endl;
}
public:
derivedclass(int n)
{
m_mynumber = n;
}
};
void main()
{
// Here use the middleclass instead of the baseclass
middleclass *bObj = new derivedclass(10);
// printmynumber is deleted in the middleclass and can't be called
// This will result in a build error
bObj->printmynumber();
delete bObj;
}
这当然需要修改所有使用原始基class的地方,但不需要修改基class本身。所以这是一个权衡。