Calling the default constructor on c structs - c++

The code below compiles just fine (unless the call to method is uncommented).
Why is it allowed to "call" to the default constructor? (there shouldn't be one)
Why is the declaration of the member function not an error?
.
extern "C"
{
struct S
{
int some_int;
void method(){}
};
}
int main()
{
S s();
// s.method();
return 0;
}

First, S s(); declares a function named s that takes no arguments and returns an object of type S. Just like int f();.
Second, that extern "C" isn't relevant here. It's used, roughly, for functions that are written in C and called from C++. It doesn't mean "pretend that this code is C code".
Third, S does have a default constructor. The compiler generates one. In this case it doesn't do anything, because there are no members of S that require non-trivial initialization. To use the default constructor you'd write S s; or S s{};.
Fourth, the reason that declaring a member function is okay is that a struct and a class in C++ can have member functions. I know, that sounds tautologous, but it's important to keep in mind that a struct can have member functions, static data, private, protected, and public members just like a class. The only differences between a struct and a class is that by default members of a class are private while members of a struct are public, and by default a base of a class is inherited privately while a base of a struct is inherited publicly.

Adding a default constructor (although it's optional here) and using curly-braces rather than parenthesis or you don't even need to use that, will solve your issue:
....
struct S {
S() {} // declaring the constructor explicitly here
};
....
int main(void) {
S s{}; // Don't use s() - a function, instead, call the
// default constructor
// S s;
s.method();
return 0;
}

Related

Initializing data members inside class body

When data members should be initialized directly inside class/struct body over using constructor?
struct A{
int x;
A() : x{3} {}
};
struct B{
int x{3};
};
The above two methods have the same effect.
Member init list must be used if the value depends on a constructor argument. It must also be used if separate constructors should initialise the member with different value. It must also be used prior to C++11, because that is the language version where the default member initialisers were introduced.
Otherwise the choice is up to the programmer. Default member initialisers are useful for avoiding repetition in constructors that initialise with the same, constant value, as well as having more concise and simpler syntax.
I would like to point out one difference.
struct B{
int x{3};
};
The above initialization applies to all the constructors where x is not explicitly initialized.
The below initialization applies ONLY to the default constructor. So if you are following below approach, you may end up with lot of boiler plate code when the value initialized is same.
struct A{
int x;
A() : x{3} {}
};

Class methd contains the same class object

Is it legal in func1 and func2? Class methd contains the same class object.
example:
class Foo
{
public:
void func1() {
//...
Foo foo; // Is it legal?
//...
}
// Is it legal in paramete?
void func2(Foo object) {
//...
}
// It is legal using reference
// http://stackoverflow.com/questions/6921185/why-do-objects-of-the-same-class-have-access-to-each-others-private-data
void func3(Foo& object) {
//
}
};
Is it legal?
yes
Why?
class Foo
{
public:
void func1() {
//...
Foo foo; // Is it legal?
//...
}
};
The body of a class member function is compiled after the entire class definition has been considered.
For this reason, the entire class is available to the method's implementation, including methods and members declared after the current method.
This is covered in [class.mem]
Within the class member-specification, the class is regarded as complete within function bodies, default arguments, using-declarations introducing inheriting constructors, exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes).
Yes, it is legal in all of your cases.
But it is illegal in constructor of copy:
// here should be 'const Foo&'
Foo(const Foo object);
Sloppy speaking, the only difference between a free function and a member function is that a member function get a this passed as first argument (you dont see it explicitly but it is there). This is not completely true, but true enough to understand that there is no reason not to have a Foo inside a member function of Foo.
What you cannot do is something like this:
struct Bar {
Bar x;
};
thats not only a quite strange construct ("its turtles all the way down", just in case you know that quote) but also your complier will clearly tell you that it cannot work.
Yes, it is legal in all of those three cases.
of course it is 100% legal, that is what many operators need as parameter, and many other functions use...
look this example taken from the String class:
string& operator+= (const string& str);
so string class has a function taking another string as parameter...

Can we avoid the default constructor in this case?

Observation: The constructor of ClassMain needs to call Init before it can constructor a member variable a. Since the ClassA has no default constructor, the code doesn't compile.
ClassA
{
public:
// This class has no default constructor
ClassA(...){}
};
class ClassMain
{
public:
ClassMain(...) {
Init(...);
a = ClassA(...); // error: ClassA has no default constructor
// a has to been constructed after the Init is called!
}
ClassMain(...) {
Init(...);
call other functions
a = ClassA(...);
}
private:
// initialize environment
void Init(...) {}
private:
ClassA a;
};
Question> The simple solution is to provide a default constructor for ClassA. However, I would like to know whether there is a better solution to address the issue above?
The better solution is not to require an Init function at all. You're trying to reinvent constructors, and breaking their design in the process.
If Init does too much work for a constructor, then do it outside and pass the resulting resources into ClassMain as a constructor argument; notice how you're already doing all the work in the constructor's scope anyway, thereby not gaining anything appreciable over proper initialisation.
Of course, if you must perform a ton of work before initialising a, and you cannot pass in a ClassA& from the outside and initialise from that, then you're simply going to have to have a be an indirect member.
There is one nasty workaround you could use: have Init actually be a base constructor...
The obvious solution is to call Init() from the initializer list of an early member or a base class. Once this subobject is constructed its results can be passed to the constructors of other subobjects. For example, when defining stream classes I typically privately inherit from a virtual base containing the stream buffer:
struct somebuf_base {
somebuf sbuf;
// ...
};
class somestream
: private virtual somebuf_base
, public std::ostream
{
public:
somestream(someargs)
: somebuf_base(someargs)
, std::ostream(&this->sbuf) {
}
// ...
};
Since base classes are constructed in the order they appear but virtual bases before non-virtual bases, the base class containing the sbuf member is constructed first. Its constructor replaces your Init() function.
When using C++ as of the 2011 revision, you might also use forwarding constructors to share logic between multiple constructors.
It's easier to take a pointer to ClassA; So, you can instantiate it whenever you want.(after the init())
If you used a pointer, don't forget to implement the virtual destructor and release the allocated memory for the ClassA *a
If you absolutely must call some function at the start of your constructor, and can't put that setup into some base class or early-constructed member, you could use this ugly trick:
ClassMain::ClassMain(int main_param)
: a( (Init(init_arg), class_a_arg1), class_a_arg2 )
{
}
In this case: No, we cannot avoid that.
The reason is that when calling Init or any other member function you are guaranteed by the language that the object you are in exists. As a is a member of ClassMain it must be constructed before any function in ClassMain can be called.
The only chance that you have here is to refactor the code.

How to delete the default constructor?

Sometimes I don't want to provide a default constructor, nor do I want the compiler to provide a system default constructor for my class. In C++ 11 I can do thing like:
class MyClass
{
public:
MyClass() = delete;
};
But currently my lecturer doesn't allow me to do that in my assignment. The question is: prior to C++ 11, is there any way to tell the compiler to stop implicitly provide a default constructor?
I would say make it private.. something like
class MyClass
{
private:
MyClass();
}
and no one(from outside the class itself or friend classes) will be able to call the default constructor. Also, then you'll have three options for using the class: either to provide a parameterized constructor or use it as a utility class (one with static functions only) or to create a factory for this type in a friend class.
Sure. Define your own constructor, default or otherwise.
You can also declare it as private so that it's impossible to call. This would, unfortunately, render your class completely unusable unless you provide a static function to call it.
Since c++11, you can set constructor = delete. This is useful in conjunction with c++11's brace initialization syntax {}.
For example:
struct foo {
int a;
foo() = delete;
foo(int _a) {
// working constructor w/ argument
}
};
foo f{}; // error use of deleted function foo::foo()
foo f{3}; // OK
see https://en.cppreference.com/w/cpp/language/default_constructor#Deleted_implicitly-declared_default_constructor
Additionally to declaring the default constructor private, you could also throw an exception when somebody tries to call it.
class MyClass
{
private:
MyClass()
{
throw [some exception];
};
}

What is the concept of default constructor?

help me in getting the concept of default constructor with example.
i don't know when to use default constructor in the program and when not to.
help me coming over this problem.explain it with an example for me.
when it is necessary to use it?
#include<iostream>
using namespace std;
class abc
{
public:
abc()
{
cout<<"hello";
}
};
int main()
{
abc a;
system("pause");
return 0;
}
so actually what is the use of default constructor and when it is necessary to use it?
A class that conforms to the concept DefaultConstrutible allows the following expressions (paragraph 17.6.3.1 of N3242):
T u; // object is default initialized
T u{}: // object is value intialized
T(); T{}; // value initialized temporary
So much for the concept. Paragraph 12.1/5 actually tells us what a default constructor is
A default constructor for a class X is a constructor of class X that
can be called without an argument. If there is no user-declared
constructor for class X, a constructor having no parameters is
implicitly declared as defaulted (8.4). An implicitly-declared default
constructor is an inline public member of its class. ...
With the introduction of deleted special member functions, the standard also defines a list of cases where no implicit default constructor is available and the distinction of trivial and non-trivial default constructors.
If you don't need to do anything as your class is instantiated. Use the default constructor, any situation else you will have to use your own constructor as the default constructor basically does nothing.
You also don't need to write any "default" constructor.
class abc {
};
int main() {
abc a; //don't want to do anything on instatiation
system("pause");
return 0;
}
class abc {
private:
int a;
public:
abc(int x) { a = x };
}
int main() {
abc a(1); //setting x to 1 on instantiation
system("pause");
return 0;
}
Constructor is a special function, without return type. Its name must be as the class\struct name. It doesn't have an actual name as a function, as Kerrek-SB pointed out.
Default constructor is the one that has no parameters, or has parameters all with a default value.
Constructor function is being called only once - when an object is instantiated
Constructor is called through a new expression or an initialization expression. It cannot be called "manually".
Useful for initializing object's fields, usually with a member initializer list.
Check this.
Default constructor is constructor with no argument and will be called on these situations:
Instancing or newing an object of a class without any constructor, like:
abc a;
abc* aptr=new abc;
Declaring an array of a class, like:
abc a_array[10];
When you have a inherited class which does not call one of base class constructors
When you have a feature in your class from another class and you don't call a definite constructor of that feature's class.
When you use some containers of standard library such as vector, for example:
vector <abc> abc_list;
In these situations you have to have a default constructor, otherwise if you do not have any constructor, the compiler will make an implicit default constructor with no operation, and if you have some constructors the compiler will show you a compile error.
If you want to do one of the above things, use a default constructor to make sure every object is being instantiated correctly.