为什么构造函数不返回值?
请告诉我为什么构造函数不返回任何值。 我想要一个完美的技术理由向我的学生解释为什么构造函数没有任何返回types。
构造函数实际发生的事情是,运行时使用编译器生成的types数据来确定将对象实例存储在内存中需要多less空间,将其放在堆栈上还是放在堆上。
这个空间包括所有的成员variables和vtbl。 在分配这个空间之后,构造函数被调用作为实例化和初始化过程的内部部分,以初始化这些字段的内容。
然后,当构造函数退出时,运行时返回新创build的实例。 所以构造函数不返回值的原因是因为它没有被你的代码直接调用,而是被运行时的内存分配和对象初始化代码所调用。
它的返回值(如果它实际上有一个编译到机器代码时)对用户来说是不透明的,所以你不能指定它。
那么,它以某种方式返回刚刚构build的实例。
你甚至可以这样称呼它,例如Java
Object o = new Something();
这看起来就像调用带有返回值的“常规”方法一样
Object o = someMethod();
(我偏向于C ++,所以关于其他语言,请带上一点盐。)
简短的回答:你不想明确地检查代码中每个对象构造的成功。
稍长的答案:在C ++中,dynamic调用构造函数以及全局和自动分配的对象。 在这个代码中
void f() { std::string s; }
s
( std::string::string()
)的构造函数没有办法返回任何值。 要么它成功了 – 那么我们可以使用这个对象,否则会抛出一个exception – 我们从来没有机会尝试使用它。
国际海事组织,这是应该的方式。
如何构造函数应该返回一个返回值? new
运算符返回新创build的实例。 你不打电话给你, new
。
MyClass instance = new MyClass();
如果Ctor会返回一个值,如下所示:
public int MyClass() { return 42; }
你会在哪里收到整数?
当你调用构造函数时,返回值是新的对象:
Point pt = new Point(1,2);
但是在构造函数本身中,实际上并没有创build和返回对象。 它是在你的代码开始之前创build的,你只需要设置初始值。
Point::Point(int x, int y) { this->x = x; this->y = y; }
缺less返回types反映了构造函数的使用与其他函数不同的事实。 返回types为null
虽然在技术上是准确的,但并不能很好地反映代码被用作返回对象的事实。 然而,任何其他的返回types都会表明你的代码应该在最后return
一些东西,这也是不正确的。
构造函数是在初始化对象的新实例时自动调用的一些方法。
如果你需要初始化你的对象到一个给定的状态并运行一些默认的方法,这个方法就在那里。
其实你可以想象构造函数总是返回创build的对象的实例,这将是一个很好的形象。
所有的答案都偏向于C ++ / Java。 构造函数没有理由不返回语言devise以外的值。
从更广义的angular度来看构造函数:它是构造新对象的函数。 你可以在C中写出完全有效的构造函数:
typedef struct object object; int object_create( object **this );
这在C中是完美的OOP,构造函数返回值(这也可以称为工厂,但名称取决于意图)。
然而,为了自动创build一个对象(例如为了满足一些types转换或转换),必须定义一些规则。 在C ++中,有一个无参数的构造函数,如果没有定义,则由编译器推断。
讨论比我们想象的更广泛。 面向对象编程是描述编程思维方式的名称。 你几乎可以使用任何语言的OO:你需要的只是结构和function。 像C ++和Java这样的主stream语言非常普遍,我们认为它们定义了“方式”。 现在看看Ada的OO模型:它远离C ++的模型,但仍然是OO。 我相信像Lisp这样的语言还有其他一些做OO的方法。
尚未讨论的一点是,类“foo”的构造函数不仅在创buildfoo实例时可用,而且在创build从foo派生的类实例时也必须可用。 如果没有generics(在deviseJava,C ++或.net时不可用),foo的构造函数将无法返回任何派生类的对象。 因此,需要发生的是派生类对象是通过其他方法创build的,然后使得foo的构造函数可以使用(然后在初始化时可以使用该对象作为foo)。
即使构造函数的虚拟机实现不是要返回任何值,实际上它也是 – 新对象的引用。 如果能够在一个语句中存储一个或两个新对象的引用和一个额外的返回值,那么在语法上就会变得奇怪和/或令人困惑。
构造函数不被用户的代码直接调用。 它由运行时的内存分配和对象初始化代码调用。 它的值对用户不可见。
在C#的情况下,声明对象的语法是:
classname objectname= new constructor();
根据这条线,如果我们使用赋值运算符(=),那么它应该返回一些值。 但是构造函数的主要目标是为variables赋值,所以当我们使用一个新的关键字时,它创build了该类的实例,而构造函数为该特定的对象实例赋值给variables,所以构造函数返回了该对象的赋值实例。
我们不能独立地调用构造函数。 相反,只要创build对象,就会自动调用它们。 例如:
MyDate md = new Mydate(22,12,2012);
在上面的例子中, new
将返回一个将由md保存的内存位置,并且以编程方式我们不能在单个语句中返回多个值。 所以构造函数不能返回任何东西。
从我所了解的OOdevise方法,我会说:
1)通过允许构造函数返回值,框架开发人员将允许程序在不处理返回值的瞬间崩溃。 为了保持程序工作stream的完整性,不允许从对象的初始化返回值是一个有效的决定。 相反,语言devise者会build议/强制编码人员使用getter / setter – 访问方法。
2)允许对象在初始化时返回一个值也会打开可能的信息泄漏。 特别是当有多个图层或访问修改应用于variables/方法时。
当你知道当创build对象时,构造函数将自动调用所以现在想象一下构造函数正在返回一个int值。 所以代码应该这样…
Class ABC { int i; public: int ABC() { i=0; return i; } ....... }; int main() { int k= ABC abc; //constructor is called so we have to store the value return by it .... }
但是当你意识到像int k= ABC abc;
在任何编程语言中都是不可能的。 希望你能理解。
我发现它有帮助
这个混淆来自假设,构造函数就像类定义的任何其他函数/方法一样。 不,他们不是。
构造函数只是对象创build过程的一部分。 它们不像其他成员函数那样被调用。
我会在答案中使用Java作为我的语言。
class SayHelloOnCreation { public SayHelloOnCreation() { System.out.println("Hello, Thanks For Creating me!"); } } class Test { public static void main(String[]args) { SayHelloOnCreation thing = new SayHelloOnCreation(); //This line here, produces an output - Hello, Thanks For Creating me! } }
现在让我们看看这里发生了什么。 在java中,我们使用new关键字来创build一个类的实例。 正如你可以在代码中看到的,在行中, SayHelloOnCreation thing = new SayHelloOnCreation(); ,赋值运算符在赋值完成之前运行后的expression式。 因此,使用关键字new ,我们调用该类的构造函数( SayHelloOnCreation() ),并且此构造函数在Java堆上创build一个对象 。 在创build对象之后,将该对象的引用分配给SayHelloOnCreationtypes的事件引用。
我试图在这里保留的一点是,如果构造函数被允许有一个返回types,那么首先强化types的语言会受到影响(记住我在这里讲的是Java)。
其次 ,类SayHelloOnCreation的对象在这里创build,所以默认情况下,我猜构造函数返回相同types的引用,以避免ClassCastException 。
所以构造函数不返回值的原因是因为它没有被你的代码直接调用,而是被运行时的内存分配和对象初始化代码所调用。 它的返回值(如果它实际上有一个编译到机器代码时)对用户来说是不透明的,所以你不能指定它。