C++ 从构造函数调用成员函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3091833/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 12:01:53  来源:igfitidea点击:

Calling member functions from a constructor

c++oop

提问by Simon Walker

I know this question has a similar title to this: C++: calling member functions within constructor?but I am asking a more general question.

我知道这个问题有一个类似的标题:C++: 在构造函数中调用成员函数?但我问的是一个更一般的问题。

Is it good practice to call member functions from within a constructor? It makes reading the code easier and I prefer the encapsulation type way of doing it (ie. each block of code has a single objective).

从构造函数中调用成员函数是一种好习惯吗?它使阅读代码更容易,我更喜欢封装类型的方式(即每个代码块都有一个目标)。

An illustrative example, in python:

一个说明性的例子,在 python 中:

class TestClass:
    def __init__(self):
        self.validate()

    def validate(self):
        # this validates some data stored in the class

Is this a better way of doing it than writing the validatecode inside the constructor? Are there drawbacks to this method? For example is it more costly with the function overhead?

这是比validate在构造函数中编写代码更好的方法吗?这种方法有缺点吗?例如,函数开销是否更昂贵?

I personally prefer it for readability but that's just my preference.

我个人更喜欢它的可读性,但这只是我的偏好。

Cheers

干杯

采纳答案by richj

I don't think there is anything inherently wrong in calling member functions from a constructor provided that they are not virtual functions.

我认为从构造函数调用成员函数没有任何本质上的错误,前提是它们不是虚函数

The problem with calling virtual member functions from a constructor is that a subclass can override the function. This will cause the constructor to call the overridden implementation in the subclass, before the constructor for the subclass part of the object has been called.

从构造函数调用虚成员函数的问题在于子类可以覆盖该函数。这将导致构造函数在调用对象子类部分的构造函数之前调用子类中被覆盖的实现。

In Java, any one of the private, staticor finalaccess modifiers will make the method safe to call from a constructor by preventing a virtual call to the superclass method. I don't think these techniques are available in Python.

在 Java 中,privatestaticfinal访问修饰符中的任何一个都会通过阻止对超类方法的虚拟调用来使从构造函数调用的方法安全。我不认为这些技术在 Python 中可用。

回答by recentlybitten

There is at least one associated "gotcha" you should be aware of:

您至少应该注意一个相关的“问题”:

N3797 12.6.2/14

N3797 12.6.2/14

Member functions (including virtual member functions, 10.3) can be called for an object under construction. Similarly, an object under construction can be the operand of the typeidoperator (5.2.8) or of a dynamic_cast(5.2.7). However, if these operations are performed in a ctor-initializer(or in a function called directly or indirectly from a ctor-initializer) before all the mem-initializers for base classes have completed, the result of the operation is undefined. [Example:

class A {
public:
   A(int);
};

class B : public A {
    int j;
public:
    int f();
    B() : A(f()),  // undefined: calls member function
                   // but base A not yet initialized
    j(f()) { }     // well-defined: bases are all initialized
};

class C {
public:
    C(int);
};

class D : public B, C {
    int i;
public:
    D() : C(f()), // undefined: calls member function
                  // but base C not yet initialized
    i(f()) { }    // well-defined: bases are all initialized
};

— end example]

可以为正在构造的对象调用成员函数(包括虚成员函数,10.3)。类似地,构造中的对象可以是运算typeid符 (5.2.8) 或 a dynamic_cast(5.2.7)的操作数。但是,如果这些操作在基类的所有mem-initializer完成之前在ctor-initializer(或从ctor-initializer直接或间接调用的函数中)执行,则操作的结果是未定义的。[示例:

class A {
public:
   A(int);
};

class B : public A {
    int j;
public:
    int f();
    B() : A(f()),  // undefined: calls member function
                   // but base A not yet initialized
    j(f()) { }     // well-defined: bases are all initialized
};

class C {
public:
    C(int);
};

class D : public B, C {
    int i;
public:
    D() : C(f()), // undefined: calls member function
                  // but base C not yet initialized
    i(f()) { }    // well-defined: bases are all initialized
};

— 结束示例]

回答by Michael Borgwardt

The main problem with this is that the member function has to work with an object that may be only partially initialized. And if it (even accidentally) passes a reference to the object somewhere else, other code has to od the same. This can get pretty confusing and error-prone, especially once you start overriding such a function in a subclass.

这样做的主要问题是成员函数必须处理可能仅部分初始化的对象。如果它(甚至是意外地)在其他地方传递了对对象的引用,则其他代码必须相同。这会变得非常混乱和容易出错,尤其是当您开始在子类中覆盖这样的函数时。

So in general, this practice should be avoided or at least confined to functions that can't be overriden, and they should never pass a reference to the object being constructed to any other code.

所以一般来说,这种做法应该避免或至少限于不能被覆盖的函数,并且它们不应该将正在构造的对象的引用传递给任何其他代码。

回答by Reinderien

I'm more familiar with C++ than Python, but I see no problem with calling member functions from constructors, especially when this practice is able to factor out similar code from multiple constructors. Anything that reduces redundancy is good in my books.

我对 C++ 比 Python 更熟悉,但我认为从构造函数调用成员函数没有问题,尤其是当这种做法能够从多个构造函数中提取出类似的代码时。在我的书中,任何减少冗余的东西都是好的。

回答by Denis 'Alpheus' Cahuk

From a readability point of view it is definitely better. One thing you might have to ask yourself here though is whether the validate method is allowed to run afterthe object is initialized. If that is not the case, you can a) use some kind of private initializedvariable or b) use the Builder patternto get your objects into a valid state before using them.

从可读性的角度来看,它肯定更好。不过,您可能需要在这里问自己的一件事是,是否允许在对象初始化运行验证方法。如果不是这种情况,您可以 a) 使用某种私有初始化变量或 b) 使用Builder 模式使您的对象在使用之前进入有效状态。

Make sure the function is private. You do not want to mess with subclasses overriding it (Unless this is desired by design, in which case make it abstract/virtual).

确保该功能是私有的。您不想弄乱覆盖它的子类(除非设计需要这样做,在这种情况下将其设为抽象/虚拟)。