views:

346

answers:

8

Hi,

Just out of curiosity: Why C++ choose a = new A instead of a = A.new as the way to instantiate an object? Doesn't latter seems more like more object-oriented?

A: 

I reckon there is no reason. Its a = new a just because it was first drafted that way. In hindsight, it should probably be a = a.new();

Andrew Keith
`a = a.new` would seem very inconsistent to me. Assuming that `a` is an `A*`, surely `a->new` would be more consistent but even so why would you have a syntax that might indicate use of an uninitialized pointer in the construction of the new object that it's being initialized to point at?
Charles Bailey
`A::new` would be more meaningful, since it'd have to be a static operation. It doesn't yet have an object to operate on. And yes, it would be pointless and inconsistent.
jalf
@jalf: `A::new` is already taken by the language! The class is allowed to implement a static `operator::new` which is one half of what keyword `new` does.
Troubadour
true, but the question was why C++ chose to implement it this way, not how a member-like syntax can be bolted onto the existing C++. If C++ had settled on a "member-like" syntax, then for consistency, it should have been `A::new`.
jalf
And also, it's `A::operator new`, so `A::new` is still available. Notice that `::new` is also valid, so having `A::new` be valid would seem logical to me.
Johannes Schaub - litb
@litb: Woops, good point.
Troubadour
+1  A: 

A.new is a static function of A while a = new A allocates memory and calls the object's constructor afterwards

Etan
+11  A: 

The . in C++ is only used for member access so the right hand side of the dot is always an object and not a type. If anything it would be more logical to do A::new() than A.new().

In any case, dynamic object allocation is special as the compiler allocates memory and constructs an object in two steps and adds code to deal with exceptions in either step ensuring that memory is never leaked. Making it look like a member function call rather than a special operation could be considered as obscuring the special nature of the operation.

Charles Bailey
+1, but it wouldn't be much more logical to do A::new() as long as there's no `new()` member, returning A*.
Michael Krelin - hacker
But that is my point. A::new() would very much be like a static member. As `new` is a key word and we're talking about 'what if' in the language rules, we can specify that users aren't allowed to define their own member functions called `new` (as is the case now).
Charles Bailey
I know it's your point, that's why +1. It wasn't exactly your words, hence the comment ;-)
Michael Krelin - hacker
OK, I thought you were pointing out a necessary extra condition. I was just saying that it could be "ruled out". :)
Charles Bailey
No, just picking at the "it would be more logical to do A::new() than A.new()" wording. It's hard to argue whether it's more or less logical, so I just added that it wouldn't be *much* more logical ;-)
Michael Krelin - hacker
Also notice that `::new` is already allowed. Enhancing it to make `A::new` possible indeed seems to be more logical to me.
Johannes Schaub - litb
+1  A: 

Actually, you can instantiate object with something like A.new, if you add the proper method:

class A{
  public: static A* instance()
  {  return new A(); }
};

A *a = A::instance();

But that's not the case. Syntax is not the case either: you can distinguish :: and . "operations" by examining right-hand side of it.

I think the reason is memory management. In C++, unlike many other object-oriented languages, memory management is done by user. There's no default garbage collector, although the standard and non-standard libraries contain it, along with various techniques to manage memory. Therefore the programmer must see the new operator to understand that memory allocation is involved here!

Unless having been overloaded, the use of new operator first allocates raw memory, then calls the object constructor that builds it up within the memory allocated. Since the "raw" low-level operation is involved here, it should be a separate language operator and not just one of class methods.

Pavel Shved
Thanks for the edit but I fear use of the word "operator" here is still misleading to someone not familiar with this area. The new operator doesn't construct anything. Keyword new has two stages, namely calling the appropriate new operator and then constructing the object at the address returned by the operator.
Troubadour
+3  A: 

I think the biggest confusion here is that new has two meanings: there's the built-in new-expression (which combines memory allocation and object creation) and then there's the overloadable operator new (which deals only with memory allocation). The first, as far as I can see, is something whose behavior you cannot change, and hence it wouldn't make sense to masquerade it as a member function. (Or it would have to be - or look like - a member function that no class can implement / override!!)

This would also lead to another inconsistency:

 int* p = int.new;

C++ is not a pure OOP language in that not everything is an object.

C++ also allows the use of free functions (which is encouraged by some authors and the example set in the SC++L design), which a C++ programmer should be comfortable with. Of course, the new-expression isn't a function, but I don't see how the syntax reminding vaguely of free-function call can put anybody off in a language where free function calls are very common.

UncleBens
+1 for pointing out the often overlooked difference between keyword `new` and `operator::new`.
Troubadour
Well, actually evrything in storage is an *object*. What you probably meant to say by your 'int' example is that not every type in C++ is a *class type*.
AndreyT
+12  A: 

Just out of curiosity: Why C++ choose a = new A instead of a = A.new as the way to instance-lize an object? Doesn't latter seems more like more object-oriented?

Does it? That depends on how you define "object-oriented".

If you define it, the way Java did, as "everything must have syntax of the form "X.Y", where X is an object, and Y is whatever you want to do with that object, then yes, you're right. This isn't object-oriented, and Java is the pinnacle of OOP programming.

But luckily, there are also a few people who feel that "object-oriented" should relate to the behavior of your objects, rather than which syntax is used on them. Essentially it should be boiled down to what the Wikipedia page says:

Object-oriented programming is a programming paradigm that uses "objects" – data structures consisting of datafields and methods together with their interactions – to design applications and computer programs. Programming techniques may include features such as information hiding, data abstraction, encapsulation, modularity, polymorphism, and inheritance

Note that it says nothing about the syntax. It doesn't say "and you must call every function by specifying an object name followed by a dot followed by the function name".

And given that definition, foo(x) is exactly as object-oriented as x.foo(). All that matters is that x is an object, that is, it consists of datafields, and a set of methods by by which it can be manipulated. In this case, foo is obviously one of those methods, regardless of where it is defined, and regardless of which syntax is used in calling it.

C++ gurus have realized this long ago, and written articles such as this. An object's interface is not just the set of member methods (which can be called with the dot syntax). It is the set of functions which can manipulate the object. Whether they are members or friends doesn't really matter. It is object-oriented as long as the object is able to stay consistent, that is, it is able to prevent arbitrary functions from messing with it.

So, why would A.new be more object-oriented? How would this form give you "better" objects?

One of the key goals behind OOP was to allow more reusable code.

If new had been a member of each and every class, that would mean every class had to define its own new operation. Whereas when it is a non-member, every class can reuse the same one. Since the functionality is the same (allocate memory, call constructor), why not put it out in the open where all classes can reuse it? (Preemptive nitpick: Of course, the same new implementation could have been reused in this case as well, by inheriting from some common base class, or just by a bit of compiler magic. But ultimately, why bother, when we can just put the mechanism outside the class in the first place)

jalf
+1 for noting that Object Orientation has absolutely nothing to do with syntax.
Tom
+2  A: 

please read the code (it works), and then you'll have different ideas:

CObject *p = (CObject*)malloc(sizeof *p);
...
p = new(p) CObject;
p->DoSomthing();
...
EffoStaff Effo
Yes, so-called "placement new" where `operator::new` does nothing but return the pointer passed into it and so construction is performed at that address i.e. a technique to manually call a constructor.
Troubadour
A: 

Why one should have seperate new of each class ?

I dont think its needed at all because the objective of new is to allocate appropriate memory and construct the object by calling constructor. Thus behaviour of new is unique and independent irrespective of any class. So why dont make is resuable ?

You can override new when you want to do memory management by yourself ( i.e. by allocating memory pool once and returning memory on demand).

Ashish