C++ 成员如何知道它是在哪个类实例中构造的?

C++ 成员如何知道它是在哪个类实例中构造的?,c++,constructor,C++,Constructor,对于x的构造函数来说,有没有一种优雅的方法可以隐式地知道它在构造什么样的C实例? 我用一些肮脏的不雅的机器实施了这种行为。我的sqlite3包装器需要这个。我不喜欢我见过的所有包装,它们的API既难看又不方便。我想要这样的东西: class C { public T x; }; 致dribeas: 我的目标是避免重复和乏味的打字。如果没有一些技巧,我必须为每个字段和参数键入: TestRecordset(wstring param_value):

对于x的构造函数来说,有没有一种优雅的方法可以隐式地知道它在构造什么样的C实例? 我用一些肮脏的不雅的机器实施了这种行为。我的sqlite3包装器需要这个。我不喜欢我见过的所有包装,它们的API既难看又不方便。我想要这样的东西:


    class C {
    public
      T x;
    };
致dribeas: 我的目标是避免重复和乏味的打字。如果没有一些技巧,我必须为每个字段和参数键入:

TestRecordset(wstring param_value): Recordset(open_database(L"test.db")), param("PARAM") { param = param_value; fetch(); } 这是多余的,丑陋的和不方便的。例如,如果我必须在 在选择的中间,我必须重写所有的列号。 您的帖子上的一些注释:

字段和参数由其默认构造函数初始化。 构造函数中初始值设定项的顺序无关。字段总是按照其声明的顺序进行初始化。我用这个事实来跟踪字段的列索引 首先构造基类。所以,当字段被构造时,记录集中的内部字段列表就可以由字段默认构造函数使用了。 我不能在这里使用RAII。我需要在Recorset构造函数中获取锁,并在构建完所有字段后在TestRecordset构造函数中释放它。
不需要。对象不需要知道从何处使用才能工作。就x而言,它是T的一个例子,就是这样。根据它是C类的成员、D类的成员、自动的、临时的等等,它的行为没有什么不同

此外,即使T构造函数确实知道C的实例,C的实例也将是不完整的,因为它当然还没有完成构造,因为它的成员还没有被构造。C++提供了大量的机会来让自己在脚下开枪,但是提供给另一个类构造函数中的不完整对象的引用不是其中之一。 我唯一能想到的接近你的代码示例的方法是

TestRecordset(wstring param_value): Recordset(open_database(L"test.db")), param(this, "PARAM"), field1(this, 0), field2(this, 1), field3(this, 2) { ... } 紧跟在字段列表之后,然后在初始值设定项列表中使用INIT_字段并取消对其定义。它仍然是复制品,但至少都在一个地方。然而,这可能会让你的同事感到惊讶

另一种确保不会忘记字段的方法是从字段中删除零参数构造函数。同样,您仍然需要进行键入,但至少如果您忘记了某些内容,编译器会捕获它。我认为,初始化列表的非干燥性质是C++所必须具备的。

< P>我不这么认为。 纯粹出于好奇,这有什么关系?您是否有这样一个环境,在其中这可能是有用的


M.

再加上一个接一个的答案,你应该问的实际问题是:我的解决方案设计有什么错,它要求对象知道它们实例化的位置?

我一直在C中进行类似的实验——我使用反射来实现

考虑为C++提供一个反射或代码生成库来帮助你做你想做的事情。


<>现在,我不能告诉你如何找到一个好的C++的反射或代码生成库,但这是一个不同的问题!p> 我对你的代码感兴趣。您认为所有字段加上param属性都有返回TestRecordSet的指针,但它们不需要初始化?或者这是问题的目的,如何避免在构造过程中必须通过this指针

如果您希望避免在构造函数的初始化列表中添加所有字段,那么这是一个有缺陷的目标。您应该始终初始化初始化列表中的所有成员,并按照它们在类中声明的相同顺序进行初始化。这不是语言强制的,而是一种全球学习的体验

您对try构造函数块的使用几乎就是他唯一推荐的功能用法,如果确实需要,任何感兴趣的人都可以阅读。如果记录集成员已被构造,因此获得了锁,并且随后在构造函数中出现错误,则[请参见下面的引文]记录集将被销毁,如果它在内部使用RAII,则将释放锁,因此我认为可能并不需要try/catch

C++03,15.2异常处理/构造函数和析构函数

一个部分是空的物体 建造的或部分毁坏的 将对所有对象执行析构函数 其完全构造的子对象, 也就是说,对于 构造函数已完成执行 而毁灭者还没有开始 执行


不不不,这个定义是UGRAOL的课程,但这是一个丑陋的问题:我如何不键入我必须键入的东西,以便C++做我想做的事?我没有说我认为这是个好主意,我说我认为这是我能想到的最接近的。我要做的是在最后一个阶段中所说的,或者,换句话说,C++初始化器语法也很难看,但这并不是。
意味着没有人使用它-我不同意你的说法,必须打字。你不必这么做。您必须支付一些费用,但实施这种行为是可能的。我引用的代码是工作代码的一部分。我能想到的一个技巧是记录集的构造函数将其存储在全局中,字段的构造函数读取它并将其转换为TestRecordSet*。我称之为黑客,因为我不喜欢为线程非安全性设计:这就是锁的用途吗?反射成本太高了。我对目前为止所得到的更好。我实际上写了一个答案,抱怨构造函数中缺少RAII,但后来当我注意到基类构造函数调用时删除了它。另一方面,在记录集构造函数中解锁不是更好吗,还有?没有。我需要在所有文件和参数构造完成后在记录集构造函数中获取qcquire lock,并在TestRecordset构造函数中强制释放lock。如果您没有用户定义的ctor或dtor或私有数据或任何使其非pod的数据,您可以使用offsetof宏获取父对象中的偏移量,然后,您可以使用该值计算父对象的指针 TestRecordset(wstring param_value): Recordset(open_database(L"test.db")), param(this, "PARAM"), field1(this, 0), field2(this, 1), field3(this, 2) { ... }
#define INIT_FIELDS field1(this), field2(this), field3(this)