- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
假设我有一个 MyClass 类,我想在其中添加某些“观察者”行为。然后我可以这样定义类:
class MyClass : public IObserver
{
...
};
现在假设这个“观察者”功能与类没有直接关系,但与存储在类中的数据成员有关。例如。数据成员指向另一个类 OtherClass,如果它引用的实例被删除,则需要将其设置为 NULL:
class PointerToOtherClass : public IObserver
{
...
};
class MyClass
{
private:
PointerToOtherClass m_ptr;
};
在这种情况下,我们甚至可以使用智能指针来编写更简单的代码。
现在假设如果 OtherClass 实例被删除,我们不只是将指针指向 NULL,我们还想删除 MyClass。因此,让 PointerToOtherClass 成为观察者已经不够了,MyClass 也应该成为观察者。但是,这意味着数据成员 m_ptr 不能自己实现全部功能(改变它的值),还需要在父类中放置一些功能。
解决方案可能是将指向 MyClass 的指针传递给 PointerToOtherClass 成员。如果 MyClass 然后实现观察者,则可以通过 PointerToOtherClass 实例轻松完成“注册”和“注销”MyClass 观察者的操作。
template <typename ParentType>
class PointerToOtherClass
{
public:
PointerToOtherClass(ParentType *parent) : m_parent(parent) {}
void setValue (OtherClass *c) { /* unregister/register m_parent */ }
private:
ParentType *m_parent;
};
class MyClass : public IObserver
{
public:
MyClass() : m_ptr(this) {}
private:
PointerToOtherClass m_ptr;
};
虽然这可以正常工作并且可以概括为一种智能指针,但我们牺牲了 4 个字节(32 位环境),因为数据成员需要指向其父级。这看起来并不多,但如果应用程序中有数百万个 MyClass 实例,并且 MyClass 有十个或更多这样的数据成员,这可能会很大。
因为 m_ptr 是 MyClass 的成员,看起来应该可以从指向 m_ptr 的指针开始获取指向 MyClass 的指针。或者,换句话说:PointerToOtherClass 中的方法应该能够通过减去 MyClass 中 m_ptr 的偏移量将其“this”指针转换为指向 MyClass 的指针。
这让我产生了以模板化方式编写此代码的想法。在以下代码中,模板化的 HostAwareField 模板类通过减去作为模板参数传递的偏移量来访问其父级:
#include <iostream>
typedef unsigned char Byte;
template <typename ParentType,size_t offset>
class HostAwareField
{
public:
ParentType *getParent() const {return (ParentType *)(((Byte *)this)-offset);}
void printParent() {std::cout << "Parent=" << getParent()->m_name << std::endl;}
};
class X
{
public:
X (char *name) : m_name(name) {}
char *m_name;
HostAwareField<X,offsetof(X,m_one)> m_one;
};
void main()
{
std::cout << "X::m_one: offset=" << offsetof(X,m_one) << std::endl;
X x1("Ross");
X x2("Chandler");
X x3("Joey");
x1.m_one.printParent();
x2.m_one.printParent();
x3.m_one.printParent();
}
但是,这不会编译。它报告以下错误:
test.cpp(18) : error C2027: use of undefined type 'X'
test.cpp(14) : see declaration of 'X'
test.cpp(18) : error C2227: left of '->m_one' must point to class/struct/union/generic type
test.cpp(16) : error C2512: 'HostAwareField' : no appropriate default constructor available
test.cpp(26) : error C2039: 'm_two' : is not a member of 'X'
test.cpp(14) : see declaration of 'X'
test.cpp(32) : error C2662: 'HostAwareField<ParentType,offset>::printParent' : cannot convert 'this' pointer from 'HostAwareField' to 'HostAwareField<ParentType,offset> &'
Reason: cannot convert from 'HostAwareField' to 'HostAwareField<ParentType,offset>'
Conversion requires a second user-defined-conversion operator or constructor
test.cpp(33) : error C2662: 'HostAwareField<ParentType,offset>::printParent' : cannot convert 'this' pointer from 'HostAwareField' to 'HostAwareField<ParentType,offset> &'
Reason: cannot convert from 'HostAwareField' to 'HostAwareField<ParentType,offset>'
Conversion requires a second user-defined-conversion operator or constructor
test.cpp(34) : error C2662: 'HostAwareField<ParentType,offset>::printParent' : cannot convert 'this' pointer from 'HostAwareField' to 'HostAwareField<ParentType,offset> &'
Reason: cannot convert from 'HostAwareField' to 'HostAwareField<ParentType,offset>'
Conversion requires a second user-defined-conversion operator or constructor
test.cpp(36) : error C2039: 'm_two' : is not a member of 'X'
test.cpp(14) : see declaration of 'X'
test.cpp(36) : error C2228: left of '.printParent' must have class/struct/union
test.cpp(37) : error C2039: 'm_two' : is not a member of 'X'
test.cpp(14) : see declaration of 'X'
test.cpp(37) : error C2228: left of '.printParent' must have class/struct/union
test.cpp(38) : error C2039: 'm_two' : is not a member of 'X'
test.cpp(14) : see declaration of 'X'
test.cpp(38) : error C2228: left of '.printParent' must have class/struct/union
如果我更改以下行:
HostAwareField<X,offsetof(X,m_one)> m_one;
到这一行:
HostAwareField<X,4> m_one;
然后这段代码可以正常工作,但需要我手动“计算”偏移量,如果添加、删除或重组数据成员可能会导致错误。
这意味着虽然我不能自动执行此操作,但我可以硬编码偏移量(如上面的值 4)并随后执行检查(以查看 4 是否真的是类中 m_one 的偏移量),但这需要额外的人工检查,使整个系统不防水。
有没有办法让上面的源代码正确编译?还是有其他技巧可以实现我想做的事情?
最佳答案
我认为必须在 offsetof
之前完全声明成员可用于确定其偏移量。这是有道理的,因为由于字节对齐规则,成员的类型会影响其偏移量。 (实际上可能也必须先声明整个类。)
在HostAwareField<X,offsetof(X,m_one)> m_one;
类型需要 offsetof
在它可以完全宣布之前工作。但是offsetof
需要声明类型才能工作。我认为没有任何方法可以进行编译。
顺便说一下,我想不出对这个设计有任何简单的修改,可以让它在每个成员不需要额外字节的情况下工作,这当然会破坏既定的目的。
也许您可以修改整体设计,使封闭类成为观察者。然后让它分派(dispatch)给适当的成员并检查某种返回值以确定它是否需要取消注册或对封闭类执行任何必要的操作。
关于c++ - 在不牺牲内存的情况下获取数据成员的 'parent' 或 'host' 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3759895/
初学者 android 问题。好的,我已经成功写入文件。例如。 //获取文件名 String filename = getResources().getString(R.string.filename
我已经将相同的图像保存到/data/data/mypackage/img/中,现在我想显示这个全屏,我曾尝试使用 ACTION_VIEW 来显示 android 标准程序,但它不是从/data/dat
我正在使用Xcode 9,Swift 4。 我正在尝试使用以下代码从URL在ImageView中显示图像: func getImageFromUrl(sourceUrl: String) -> UII
我的 Ubuntu 安装 genymotion 有问题。主要是我无法调试我的数据库,因为通过 eclipse 中的 DBMS 和 shell 中的 adb 我无法查看/data/文件夹的内容。没有显示
我正在尝试用 PHP 发布一些 JSON 数据。但是出了点问题。 这是我的 html -- {% for x in sets %}
我观察到两种方法的结果不同。为什么是这样?我知道 lm 上发生了什么,但无法弄清楚 tslm 上发生了什么。 > library(forecast) > set.seed(2) > tts lm(t
我不确定为什么会这样!我有一个由 spring data elasticsearch 和 spring data jpa 使用的类,但是当我尝试运行我的应用程序时出现错误。 Error creatin
在 this vega 图表,如果我下载并转换 flare-dependencies.json使用以下 jq 到 csv命令, jq -r '(map(keys) | add | unique) as
我正在提交一个项目,我必须在其中创建一个带有表的 mysql 数据库。一切都在我这边进行,所以我只想检查如何将我所有的压缩文件发送给使用不同计算机的人。基本上,我如何为另一台计算机创建我的数据库文件,
我有一个应用程序可以将文本文件写入内部存储。我想仔细看看我的电脑。 我运行了 Toast.makeText 来显示路径,它说:/数据/数据/我的包 但是当我转到 Android Studio 的 An
我喜欢使用 Genymotion 模拟器以如此出色的速度加载 Android。它有非常好的速度,但仍然有一些不稳定的性能。 如何从 Eclipse 中的文件资源管理器访问 Genymotion 模拟器
我需要更改 Silverlight 中文本框的格式。数据通过 MVVM 绑定(bind)。 例如,有一个 int 属性,我将 1 添加到 setter 中的值并调用 OnPropertyChanged
我想向 Youtube Data API 提出请求,但我不需要访问任何用户信息。我只想浏览公共(public)视频并根据搜索词显示视频。 我可以在未经授权的情况下这样做吗? 最佳答案 YouTube
我已经设置了一个 Twilio 应用程序,我想向人们发送更新,但我不想回复单个文本。我只是想让他们在有问题时打电话。我一切正常,但我想在发送文本时显示传入文本,以确保我不会错过任何问题。我正在使用 p
我有一个带有表单的网站(目前它是纯 HTML,但我们正在切换到 JQuery)。流程是这样的: 接受用户的输入 --- 5 个整数 通过 REST 调用网络服务 在服务器端运行一些计算...并生成一个
假设我们有一个名为 configuration.js 的文件,当我们查看内部时,我们会看到: 'use strict'; var profile = { "project": "%Projec
这部分是对 Previous Question 的扩展我的: 我现在可以从我的 CI Controller 成功返回 JSON 数据,它返回: {"results":[{"id":"1","Sourc
有什么有效的方法可以删除 ios 中 CBL 的所有文档存储?我对此有疑问,或者,如果有人知道如何从本质上使该应用程序像刚刚安装一样,那也会非常有帮助。我们正在努力确保我们的注销实际上将应用程序设置为
我有一个 Rails 应用程序,它与其他 Rails 应用程序通信以进行数据插入。我使用 jQuery $.post 方法进行数据插入。对于插入,我的其他 Rails 应用程序显示 200 OK。但在
我正在为服务于发布请求的 API 调用运行单元测试。我正在传递请求正文,并且必须将响应作为帐户数据返回。但我只收到断言错误 注意:数据是从 Azure 中获取的 spec.js const accou
我是一名优秀的程序员,十分优秀!