Private constructor

A

Andy

1) Is there any use of defining a class with a single constructor
declared in private scope? I am not asking a about private copy
constructors to always force pass/return by reference.

2) Is this in any way used to create singletons. Can someone say how?

Cheers,
Andy
 
M

Matej Pivoluska

Andy said:
1) Is there any use of defining a class with a single constructor
declared in private scope? I am not asking a about private copy
constructors to always force pass/return by reference.

2) Is this in any way used to create singletons. Can someone say how?

If you want to create singletons, you have to declare all your constructors
(and operator=, too) as private.

Then you create a public function that checks if singleton was created
(through some static bool member) and then calls (private) constructor.

Then (if check passed) your function returns refernece (or pointer) on your
singleton and set true flag to static member -- singleton was created.
 
J

jeffc

Andy said:
1) Is there any use of defining a class with a single constructor
declared in private scope? I am not asking a about private copy
constructors to always force pass/return by reference.

2) Is this in any way used to create singletons. Can someone say how?

The point of making a constructor private is usually to NOT allow anyone to
use it. (Imagine that instead of the "private" keyword it was
"inaccessible".) That allows you to have a class available for use, but not
for anyone to just create one with a plain constructor. Normally you'd
provide some other means for creating one, where you can control whether it
gets created or not. For example, you could have a static function called
"create", and that would have to be called to get a new object. In the
create function, you can first check to see if you've created one before, by
keeping a flag or counter. If so, you don't create one. If not, you create
one and return one. That way no more than one can ever exist.
 
A

Andy

jeffc said:
The point of making a constructor private is usually to NOT allow anyone to
use it. (Imagine that instead of the "private" keyword it was
"inaccessible".) That allows you to have a class available for use, but not
for anyone to just create one with a plain constructor. Normally you'd
provide some other means for creating one, where you can control whether it
gets created or not. For example, you could have a static function called
"create", and that would have to be called to get a new object. In the
create function, you can first check to see if you've created one before, by
keeping a flag or counter. If so, you don't create one. If not, you create
one and return one. That way no more than one can ever exist.

Just one question - even the static creator function needs to create
an instance of the class on the heap or stack. Without a constructor
how can that be made possible. Or is it that everything is static and
the singleton is stateless? So we never need an instance. I think I am
missing something.
 
K

Karl Heinz Buchegger

Andy said:
Just one question - even the static creator function needs to create
an instance of the class on the heap or stack. Without a constructor
how can that be made possible. Or is it that everything is static and
the singleton is stateless? So we never need an instance. I think I am
missing something.

Detail!
He didn't say that the class dosn't have a constructor (which by the
way is impossible). He said that the constructor is private! And
like an other private class member it can be used from a class member
function only. Since the static creator function is a member function,
it can use the constructor.
 
K

Karl Heinz Buchegger

Karl said:
Detail!
He didn't say that the class dosn't have a constructor (which by the
way is impossible).

Sorry. POD's indeed don't have a constructor.
 
J

jeffc

Andy said:
Just one question - even the static creator function needs to create
an instance of the class on the heap or stack. Without a constructor
how can that be made possible. Or is it that everything is static and
the singleton is stateless? So we never need an instance. I think I am
missing something.

What I wrote was a little misleading. When I said "NOT allow anyone to use
it", I didn't mean literally anyone. I mean anyone *else* outside the
class. The class itself can access its own private constructor. See Karl's
answer. e.g.

class A
{
private:
A() {}
public:
static A* createAnA();
};

A* A::createAnA()
{
return new A;
}

int main()
{
A* pA = A::createAnA();
}
 
A

Andy

jeffc said:
What I wrote was a little misleading. When I said "NOT allow anyone to use
it", I didn't mean literally anyone. I mean anyone *else* outside the
class. The class itself can access its own private constructor. See Karl's
answer. e.g.

I am sorry I made a stupid mistake. I was under the impression that
just as static functions cannot access instance data members of a
class, they also cannot call non-static member functions. Of course
member functions are not per instance even if they are made to look
that way. Constructor being a special kind of such a function should
be accessible from static member functions.
class A
{
private:
A() {}
public:
static A* createAnA();
};

A* A::createAnA()
{
return new A;
}

int main()
{
A* pA = A::createAnA();
}

I was just wondering, though this is purely a design issue, what
happens to the pointer that we get from the CreateAnA creator
function. The client code will need to explicitly call "delete" on
this pointer -- not a good thing. We would perhaps need a manager
class in between which takes care of calling delete in its destructor
.... or may be something like an auto_ptr type smart and cocky pointer
pretenders.

The singleton
--------------

The code snippet that you gave does not serve a singleton though. How
do we do that. I tried doing it this way:

----->

#include <iostream>

class CPrivCons
{
private:
CPrivCons(int n) : m_nInt(n)
{
s_cRefCnt=0;
s_This = NULL;
}

int m_nInt;
static int s_cRefCnt;
static CPrivCons *s_This;

public:
static CPrivCons& CreateObj(int n)
{
if(s_cRefCnt==0){
std::cout<<"NewInstanceCreated"<<std::endl;

s_This = new CPrivCons(n);
}

s_cRefCnt++;

return *s_This;
}

static void DestroyObj()
{
if(--s_cRefCnt == 0){
std::cout<<"ObjectDestroyed"<<std::endl;

delete s_This;
}
}

int get_IntVal()
{
int n = m_nInt;

return n;
}

void set_IntVal(int n)
{
m_nInt = n;
}
};

int CPrivCons::s_cRefCnt = 0;
CPrivCons *CPrivCons::s_This = NULL;


int main()
{
CPrivCons& p = CPrivCons::CreateObj(10);

CPrivCons& p1 = CPrivCons::CreateObj(12);

std::cout<<p.get_IntVal()<<std::endl;

std::cout<<p1.get_IntVal()<<std::endl;;

p1.set_IntVal(19);

std::cout<<p.get_IntVal()<<std::endl;

CPrivCons::DestroyObj();
CPrivCons::DestroyObj();

return 0;
}


<-----


The above code can of course not be used in a multi-threaded
situation. Besides, I feel there should be a separate manager
interface interposed between the singleton and the client.

Cheers,
Andy
 
A

Andy

<
I am sorry I made a stupid mistake. I was under the impression that
just as static functions cannot access instance data members of a
class, they also cannot call non-static member functions. Of course
member functions are not per instance even if they are made to look
that way. Constructor being a special kind of such a function should
be accessible from static member functions.
That was stupider on second thoughts. A constructor does not get a
this pointer secretly. So it's not a special kind of the others ... it
is special and different from the rest. Nevertheless, I think I am
right in assuming that neither the member functions nor the
constructor or destructor constitute the state of an instantiated
object - therefore static member functions should be able to access
them.
 
R

Ron Natalie

Andy said:
<
I am sorry I made a stupid mistake. I was under the impression that
just as static functions cannot access instance data members of a
class, they also cannot call non-static member functions. Of course
member functions are not per instance even if they are made to look
that way. Constructor being a special kind of such a function should
be accessible from static member functions.

That was stupider on second thoughts. A constructor does not get a
this pointer secretly. So it's not a special kind of the others ... it
is special and different from the rest. Nevertheless, I think I am
right in assuming that neither the member functions nor the
constructor or destructor constitute the state of an instantiated
object - therefore static member functions should be able to access
them

I have no clue what you are talking about. Constructors are non-static
member functions. You can't call them. They do have this pointers.
You're confusing access with instantiation. A static member function
has access to the private members of other objects of the same class
just like non-static members of one object can access private
members of other instances of the class.
 
J

Jeff Schwab

Ron said:
I have no clue what you are talking about. Constructors are non-static
member functions. You can't call them.

They do have this pointers.
You're confusing access with instantiation. A static member function
has access to the private members of other objects of the same class
just like non-static members of one object can access private
members of other instances of the class.

Right on.
 
R

Ron Natalie

<nit> Yes, you can. Allocators do it all the time. </nit>

Sorry, totally wrong. They do not participate in name resolution, they
can't
be called. Allocators don't do it.
 
A

Alf P. Steinbach

Sorry, totally wrong. They do not participate in name resolution, they
can't
be called. Allocators don't do it.

Perhaps it's just a question of terminology.

I find it more useful to use the word "call" about any statement that
causes a function to be executed, with control returning to the next
statement.

T();

is a simple example of executing the default constructor of type T,
here on a temporary object.

new(place) T();

is a simple example of executing the default constructor of type T on
a given area of memory 'place'.

In pure C++ terminology one might elect to call the latter a placement
new, and have no problems with multiple meanings of words.

But how would you then describe it to, say, an Ada programmer?
 
J

Jeff Schwab

Ron said:
Sorry, totally wrong. They do not participate in name resolution, they
can't be called. Allocators don't do it.

I don't know what you mean. Is there a technicality that makes my use
of "call" incorrect? Where should I look for an explanation?

Thanks,
Jeff
 
R

Ron Natalie

Perhaps it's just a question of terminology.

Perhaps, but it appears yours is not accureate.
I find it more useful to use the word "call" about any statement that
causes a function to be executed, with control returning to the next
statement.

T();

If T is a type name, this is not a fucntion call. It is only a function
call, when
T has function type.

When T is a type name, you have just created a default rvalue of that type.
is a simple example of executing the default constructor of type T,
here on a temporary object.

No, it creates a temporary object. The constructor is invoked when ever an
object
that has one is created
new(place) T();

is a simple example of executing the default constructor of type T on
a given area of memory 'place'.

No, it creates an object using the placement new syntax, which means that
the
placement allocation function is called and then the constructor is invoked
on that.

In neither case are you calling the constructor, you are causing objects to
be created
and the constructor is called by the environment as a side effect.
In pure C++ terminology one might elect to call the latter a placement
new, and have no problems with multiple meanings of words.

The meaning of the words is quite well defined by the standard. The
constructor
doesn't have a name. It does not participate in name resolution. You can't
call
it, you can't get a pointer to it, you can't do anything with it other than
define it
and let the the implementation call it at the appropriate times.
But how would you then describe it to, say, an Ada programmer?

Like I just did.
 
R

Ron Natalie

Jeff Schwab said:
I don't know what you mean. Is there a technicality that makes my use
of "call" incorrect? Where should I look for an explanation?
Yes, there is no way to call a constructor. They don't have names, the do
not
participate in name resolution. You can NOT call them. They are called
by
the implementation as a side effect of creating an object.
 
A

Alf P. Steinbach

Perhaps, but it appears yours is not accureate.

If T is a type name, this is not a fucntion call. It is only a function
call, when T has function type.

If you don't think a constructor is a member function, then consult the
standard. Chapter 12 is about special member functions. Do you think
something can be a member function and not a function?


When T is a type name, you have just created a default rvalue of that type.

That's what I wrote, yes. In this you are correct.


No, it creates a temporary object.

Where did you get the idea that there is any conflict between
calling a constructor and creating an object?

The main purpose of a constructor is exactly to _strongly couple_
those two actions.


The constructor is invoked when ever an object that has one is created

What is, in your opinion, the difference between "invoked", "executed"
and "called"?


Oh yes.

it creates an object using the placement new syntax,

Yes, it does.

which means that the placement allocation function is called

There isn't necessarily a placement allocation function.


and then the constructor is invoked on that.

Is called, yes. ;-)

In neither case are you calling the constructor,

Oh yes I am.

you are causing objects to be created

Yes I am.

and the constructor is called by the environment as a side effect.

That is not meaningful in any way.


The meaning of the words is quite well defined by the standard. The
constructor doesn't have a name. It does not participate in name
resolution. You can't call it,

Oh yes I can, as demonstrated.

you can't get a pointer to it, you can't do anything with it
other than define it and let the the implementation call it at
the appropriate times.

Oh yes I can, and it's very simple: placement new is in the language
exactly for that purpose.


Like I just did.

You haven't.
 
J

Jeff Schwab

Ron said:
Yes, there is no way to call a constructor. They don't have names, the do
not
participate in name resolution. You can NOT call them. They are called
by
the implementation as a side effect of creating an object.

You said that already. I don't follow. One more time: Where should I
look for an explanation?
 
R

Ron Natalie

Alf P. Steinbach said:
If you don't think a constructor is a member function, then consult the
standard. Chapter 12 is about special member functions. Do you think
something can be a member function and not a function?

I never said the constructor wasn't a member function. I said if T in your
example was a TYPE NAME then it is not a function call. It's not the
syntax for a function call. And if you would bother reading Chapter 12
about
special member functions, you will find almost word for word the description
I gave you about the constructor NOT HAVING A NAME.
calling a constructor and creating an object?

What conflict. They are two different concepts. The constructor invocation
is part of the object creation, but you are not "calling" it with the syntax
you
gave. You need to look at the syntax for expressions.
TYPEID ( )
is an explicit type conversion (5.2.3 of the standard).
It is NOT a function call (5.2.2 of the standard),.
What is, in your opinion, the difference between "invoked", "executed">

It is called by the implemenation, not by the programmer. I specifically
said
that, but you consider to ignore it in your refusal to admit that you can't
understand
the first sentence of 12.1
There isn't necessarily a placement allocation function.

Then the program is ill-formed. In order for the syntax you wrote
to work, you must define the placement allocation function (or #include
Oh yes I am.
Please go back and read 5.2.2, 5.2.3, and 12.1.
Oh yes I can, and it's very simple: placement new is in the language
exactly for that purpose.

??? How do you get a potiner to the constructor.
 
R

Ron Natalie

You said that already. I don't follow. One more time: Where should I
look for an explanation?
5.2.2 and 5.2.3 show the syntax for function calls versus type conversion.

Given the statement :
T();

If T is a type id, then the expression is a type conversion (5.2.3),
otherwise
it has to be function name (5.2.2) to be a function call.

12.1 in the very first sentence details that constructors do not have names
and can not be called.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top