具有私有基数的函数成员指针

2024-04-02

以下代码会产生编译时错误:

'base::print':无法访问类中声明的私有成员'base_der'

不过我已经做了会员了public在派生类中。为什么这不起作用?

#include <iostream>

using namespace std;

class base
{
public:
    int i;
    void print(int i)
    {
        printf("base i\n");
    }
};

class base_der : private base
{
public:
    using base::print;
};

int main()
{
    // This works:
    base_der cls;
    cls.print(10);

    // This doesn't:    
    void (base_der::* print)(int);
    print = &base_der::print; // Compile error here
}

我认为有一些相互作用的问题导致了该错误:

  1. 指向成员类型的指针具有不直观的类型转换特征
  2. using 声明不会影响进入作用域的名称的类型
  3. 而名字base_der::print是可访问的,类base仍然不是,在尝试转换指向成员的指针时,指向成员类型的指针中类的实际类型是考虑因素的一部分。

C++03 7.3.3“using 声明”

using 声明将名称引入到该 using 声明出现的声明区域中。该名称是在其他地方声明的某个实体名称的同义词。

请注意,虽然该名称被引入新的“区域”,但它是一个同义词 - 该名称所指的类型是相同的。所以,我认为在你的例子中,名字base_der::print有一个类型void (base::*)(int),不输入void (base_der::*)(int).

C++03 标准还提到了关于指针到成员类型之间的转换(4.11“指向成员转换的指​​针”):

“指向 cv T 类型的 B 成员的指针”类型的右值(其中 B 是类类型)可以转换为“指向 cv T 类型的 D 成员的指针”类型的右值,其中 D 是派生类 ( B 的第 10 条)。如果 B 是 D 的不可访问(第 11 条)、不明确(10.2)或虚拟(10.1)基类,则需要此转换的程序是格式错误的。转换的结果引用与转换发生之前指向成员的指针相同的成员,但它引用基类成员,就好像它是派生类的成员一样。结果引用 D 的 B 实例中的成员。由于结果的类型为“指向 cv T 类型的 D 成员的指针”,因此可以使用 D 对象取消引用它。结果与使用 D 的 B 子对象取消引用指向 B 的成员的指针相同。

另请注意 7.3.3/13“使用声明”(添加了重点):

出于重载决策的目的,通过 using 声明引入派生类的函数将被视为派生类的成员。特别是,隐式 this 参数应被视为指向派生类而不是基类的指针。这对函数的类型没有影响,并且在所有其他方面该函数仍然是基类的成员。

现在,生成错误的代码示例:

// This doesn't:    
void (base_der::* print)(int);
print = &base_der::print; // Compile error here

正在尝试将“指向 D 成员的指针”转换为“指向 B 成员的指针” - 这是错误方向的转换。如果您想一下,您就会意识到为什么朝这个方向进行转换并不安全。 “指向 B 成员的指针”类型的变量可能不会与与以下对象有关的对象一起使用:class D- 但是如果你调用一个类型为“指向 D 成员的指针”的函数(这就是void (base_der::* print)(int)是),它会正确地期望this指针将指向一个D object.

无论如何,虽然我认为问题的根源是这个转换问题,但我认为您会收到有关可访问性的抱怨,因为当编译器尝试处理转换时,它首先检查base- 即使这个名字base_der::print(这是一个别名base::print) 是可访问的,因为using声明、类base仍然不是。

免责声明:此分析来自对指向成员类型的指针的细微差别缺乏经验的人。它们是 C++ 的一个领域,非常复杂,除了最简单的场景之外很难使用,并且显然存在很多可移植性问题(请参阅 Doug Clugston 的文章,http://www.codeproject.com/KB/cpp/FastDelegate.aspx http://www.codeproject.com/KB/cpp/FastDelegate.aspx,它已经足够老了,现在很多问题可能已经得到解决,但我怀疑它们还没有)。

当你说 C++ 中的某些东西是更复杂或不太容易理解的领域之一时,这已经说明了很多。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有私有基数的函数成员指针 的相关文章

随机推荐

  • 阻止 FlowType 检查 node_modules 中的错误

    我曾尝试寻找解决方案或解决此问题的方法 但没有成功 以下是描述我的流程安装以及最终我面临的问题的一些步骤 Step 1 我使用创建了一个新的反应本机项目react native init TestProject 我想配置flow http
  • 在 dotnet 新模板中包含“隐藏”文件

    我正在尝试创建一个简单的dotnet new包含我的团队使用的 默认 editorconfig 和 gitconfig 的模板 不幸的是 files 不会被包含在dotnet pack 这是我的 csproj 的一部分
  • SonataAdminBundle表单字段查询

    在 Admin 类的 SonataAdminBundle 中 我无法创建ManyToMany 字段上的 orderBy https github com sonata project SonataAdminBundle issues 328
  • 在 C++ 的 if 语句中使用多个条件

    我正在尝试在 C 中创建一个复杂的 if 语句 这将使我免于编写一大堆 if 语句 我想知道下面的代码是否确实有意义 或者我忽略了一个错误 if input choice cout lt lt Tie lt lt endl else if
  • Flyway Gradle 插件 - 循环依赖

    我有一个使用 gradle flyway gradle 插件 mybatis 生成器和 postgres 的项目 在我的 build gradle 中 我有 compileJava dependsOn myBatisGenerator 我想
  • LinkedIn 集成 r_network 和 w_messages 请求在 iOS sdk 中无法协同工作

    我已经完成了 LinkedIn 集成 并且必须向特定用户发送消息 为此 我首先要获取连接 然后发送消息 void requestTokenFromProvider OAMutableURLRequest request OAMutableU
  • 具有不重叠条目集的两列值的共同出现表

    import pandas as pd 可重复的设置 我有一个数据框 df pd DataFrame from dict A a b b c d d c b B p q p q r r p q ie A B 0 a p 1 b q 2 b
  • 如何编写 T4 模板以从 Entity Framework 6 创建 DTO?

    我有一个大型数据库 我在 Entityframework 中使用数据库优先模型 它位于互联网服务器上并通过 WCF 进行通信 域模型使用所有小写字母来表示实体 存储过程和列 属性的名称 在我的客户端应用程序中 我希望使用标准 PascalC
  • JS 可变变量可以从闭包访问[重复]

    这个问题在这里已经有答案了 所以我的 JS 编译器中有一个警告 但是你能向我解释一下这是否真的会影响我的代码的执行方式吗 for x 0 x lt levels length x var level levels x var candles
  • 通过php代码在xls表中插入图片

    问候 我必须在行 0 列 0 上插入徽标 图像 我为此使用 Spreadsheet Excel Writer 我尝试了它的 insertBitmap 方法 程序工作正常 但不显示位图图像在 xls 工作表上 而不是空白行 可能是什么原因 您
  • 分发预先经过 NGEN 处理的程序集是否有意义?

    我发现了一些关于使用 NGEN 作为安装程序的最后一步的有趣链接这个帖子 https stackoverflow com questions 522323 how do i run ngen at the end of the instal
  • 使用一个套接字创建 2 个流

    我正在尝试创建一个在互联网上运行的多人游戏 问题是我正在尝试获取流上的输入 但由于某种原因我无法使用一个套接字创建 2 个流 我将解释一下 Socket s new Socket 127 0 0 1 5001 ObjectInputStre
  • 如何将 csv 文件导入 MySQL Workbench?

    我有一个 CSV 文件 它包含 140 万行数据 因此我无法在 Excel 中打开该 csv 文件 因为它的限制约为 100 万行 因此 我想在MySQL Workbench中导入这个文件 此 csv 文件包含类似以下的列 Service
  • 如何找到图像中最密集的区域?

    考虑一个黑白图像 例如this http img13 imageshack us img13 7401 10416827 jpg 我想做的是找到白点最密集的区域 在这种情况下 有 20 21 个这样的密集区域 即 点簇构成一个密集区域 谁能
  • 以编程方式确定身份验证模式

    有没有办法以编程方式确定 SharePoint 2007 Web 应用程序是否正在使用表单身份验证 我想一种方法可能是从 web config 中读取它 但我想知道 API 中是否公开了一些属性 看看 admin Authenticatio
  • 尽早停止詹金斯管道作业

    在我们的 Jenkins Pipeline 工作中 我们有几个阶段 我想要的是 如果任何一个阶段失败 那么构建就会停止 而不是继续到进一步的阶段 以下是其中一个阶段的示例 stage Building def result sh retur
  • 核心数据单例管理器?

    有哪些技术原因不创建单例类来管理我的核心数据 我现在正在尝试做出决定 是否应该删除所有样板核心数据代码并在单例中重新实现它 Xcode 模板中的应用程序委托中的样板代码在功能上是作为单例实现的 应用程序对象是一个单例 它只维护一个委托对象
  • Office 2010 AddIn 开发 - 我可以从代码隐藏中读取用户正在使用的主题吗?

    PowerPoint 2010 提供三种默认主题 银色 黑色和蓝色 是否可以从代码隐藏中检查用户当前正在使用哪个主题 我使用此代码根据设置的主题设置界面的颜色 public static class LFTheme const int Th
  • .NET 任务实例在运行期间是否会超出范围?

    如果我在方法中有以下代码块 使用 NET 4 和任务并行库 var task new Task gt DoSomethingLongRunning task Start 并且该方法返回 该任务是否会超出范围并被垃圾收集 或者是否会运行完成
  • 具有私有基数的函数成员指针

    以下代码会产生编译时错误 base print 无法访问类中声明的私有成员 base der 不过我已经做了会员了public在派生类中 为什么这不起作用 include