I've implemented stack process.this program is supposed to work exactly the same as a real stack memory.moreover i'm trying to use Template and make the the program more generic. I've got a problem in using #define DEFAULT_SIZE 10 as the argument of class constructor.
First of all when i put DEFAULT_SIZE in the prototype of the constructor it goes smoothly:
#define DEFAULT_SIZE 10
template<typename T>
class stack {
public:
stack(int size=DEFAULT_SIZE);
private:
T *elements;
int size;
int count;
};
template<typename T>
stack<T>::stack(int s) {
cout << "--constructor called\n";
size = s;
elements = new T[size];
count = 0;
}
But when I just put DEFAULT_SIZE in outline definition of the class constructor i get this error: no appropriate default constructor available
#define DEFAULT_SIZE 10
template<typename T>
class stack {
public:
stack(int size);
private:
T *elements;
int size;
int count;
};
template<typename T>
stack<T>::stack(int s=DEFAULT_SIZE) {
cout << "--constructor called\n";
size = s;
elements = new T[size];
count = 0;
}
Finally the main of the program:
int main() {
stack<int> u;
u.push(4);
}
My question is not about "Why can templates only be implemented in the header file?" My problem is the place where I use DEFAULT_SIZE.
I suppose, the problem is just in difference of template declaration:
stack(int size);
and template definition:
stack<T>::stack(int s=DEFAULT_SIZE) {
...
}
Default values must be in declaration part, and if method signature in definition is different from declaration (you add DEFAULT_SIZE in definition) compiler is not sure you write the same constructor. Note, DEFAULT_SIZE is applied when s value not given to constructor, so you definition will work as default constructor, but declaration is constructor with one parameter.
It is mentioned in C++ specs(ยง8.3.6 pt.4) that
For non-template functions, default arguments can be added in later declarations of a function in the same scope.
So you can't assign the default value in the definition. That is the reason for not working of second approach.
While first approach will work as it is a desired behavior that you can omit the default values in the definition.
If you compile your second code snippet with Ideone for example it gives you "redeclaration of 'stack::stack(int)' may not have default arguments" (see http://ideone.com/UKIx2r).
prog.cpp:16:35: error: redeclaration of 'stack<T>::stack(int)' may not have default arguments [-fpermissive]
stack<T>::stack(int s=DEFAULT_SIZE) {
Default parameters have to be specified in the first declaration
If you declare your own constructors the default constructor will be deleted. However, your constructor will act as a default constructor as long as all parameters have default values.
Your first part declares a correct default value for the constructors parameter. Your second part does not and your compiler has no chance to use the constructor as a default constructor.
Related
This code has a templated class. The default constructor appears to call itself recursively. How can it do that? I don't understand this code. Maybe if I would be given an example without templates, just POD types, things would be clearer. I haven't encountered this construct before in C++ programming. I think that I don't understand both the constructor and the templates.
template <typename T>
class Simple {
public:
Simple(T value = T()); // What's this?
T value();
void set_value(T value);
private:
T value_;
};
template<typename T>
Simple<T>::Simple(T value) {
value_ = value;
}
template<typename T>
T Simple<T>::value() {
return value_;
}
template<typename T>
void Simple<T>::set_value(T value) {
value_ = value;
}
My question is:
What does T value = T() do?
Class Simple has a variable value of type T (Templated).
The constructor which you are pointing is a default constructor. When no parameter is supplied while creating Simple object. Then default constructor will instantiate the value object to the default constructor of T.
Either , Simple(T value = T()) is a default constructor which is instantiating value to default constructor of typed element.
Example :-
if T is String.
Simple (String value = String())
so value is now initialized to default of String().
It is just a default value as void foo(int i = 42);, there are no recursion.
foo(); is equivalent to foo(42);.
In the same way, with Simple(T value = T());
Simple<int> s{}; would be equivalent to Simple<int> s{0}; and
Simple<std::string> s{}; would be equivalent to Simple<std::string> s{std::string{}}; (empty string).
T() would call the default constructor of given T (int and std::string in my examples).
For my constructor and overloaded constructor definitions I have:
template <class T> Student<T>::Student(){}
template <class T> Student<T>::Student(string sName, int sAge) {
m_name = sName;
m_age = sAge;
}
I am getting confused on how to call a constructor with mixed parameters in the overloaded constructor.
My understanding is that if they were both ints I would do something like:
Student <int> newStudent;
newStudent(10, 15);
Student<int> is a type. Student<int> newStudent; creates a variable of that type, which means it is constructing that object. Since no arguments are included, the no-argument constructor is used.
newStudent(10, 15) is the attempting to call an ::operator()(int, int) member of that class, which may or may not be defined.
You probably want:
Student<int> newStudent("Mary", 15);
... to create a Student<int> type object in the variable newStudent.
I have the following code:
#include <iostream>
template<typename T> class DynArray
{
T *contents;
int size;
public:
explicit DynArray(int initial_size);
};
int main()
{
DynArray<std::string> b('7');
return 0;
}
My question is: how can I prevent the implicit conversion from char to int from compiling? (i.e. this line: `DynArray b('7');
You can't directly, but you can make an overload of the constructor which gets chosen first when passed a char...
explicit DynArray(char);
Make it private and don't define it, just declare it. The same as declaring but not defining a copy ctor/copy assignment operator to prevent a class from being copyable.
Or, with C++11, make it deleted (which is the new cleaner/clearer/better way of doing the above)...
explicit DynArray(char) = delete;
The print statement in the constructor's definition doesn't get printed, isn't the constructor calling correct in main? I know I am missing some point here, please point out.
#include <iostream>
#include <typeinfo>
template <typename T> class List
{
public:
template <typename T2> List (List<T2> const&);
};
template <typename T> template <typename T2> List <T> :: List (List <T2> const&)
{
std :: cout << "\nType name:" << typeid (T2).name();
}
int main ()
{
List <int> kk (List <int>);
return 0;
}
There are a couple of things wrong in your code that you might not be aware of.
List<int> kk( List<int> );
That line is not a variable definition, but rather the declaration of a function that takes a List<int> as argument and returns a List<int>, so that effectively will not call any constructor. That is know as the most-vexing-parse (you can look at different versions of it by searching in SO, or in the C++ FAQ lite)
The second issue is that you cannot possibly create any instance of the an instantiated type of List, the reason being is that the only constructor that you are providing is a templated constructor that takes a second List<U> as argument. That effectively disables the default constructor, so the only way of creating a List<T> is by already having a List<U>, and that is not possible. You can add the default constructor back:
template <typename T>
class List {
public:
List() {}
template <typename U>
List( List<U> const & ) {} // prefer const& as that will avoid unnecessary copying
};
And now you can write:
List<int> l = List<int>(); // this will call List<int>::List( List<int> const & )
And yet, that will still not call the constructor you want. The reason is a little obscure, but when copy constructing an element of a template, the compiler will not use a templated constructor. In the code above, it will implicitly define a copy constructor by doing member-wise copy constructor of the methods and call that generated constructor. That means that in most occasions where you want to provide a templated constructor you want to also provide a non-templated copy constructor.
To actually call that constructor you would have to provide a different type:
List<int> l = List<double>();
Since the types actually differ, the compiler cannot copy construct, will find that the provided templated constructor is the best overload candidate and call it.
As well as the "most vexing parse" identified by David:
you need to have at least one more constructor to create the original List object to be passed to the copy constructor,
you need to vary the parameter type in order to have the templated copy constructor invoked: as is you'll match the implicitly declared List(const List&) copy constructor instead.
So:
#include <iostream>
template <typename T>
struct X
{
X() { std::cout << "X()\n"; }
// implicitly like this anyway...
// X(const X& rhs) { std::cout << "X(X&)\n"; }
template <typename U>
X(const U& u) { std::cout << "U\n"; }
};
int main()
{
X<int> x;
X<int> y(x);
}
What are you trying to do with this statement:
List <int> kk (List <int>);
(It actually declares a function, and can't be anything but
a function declaration.)
In order to see output from the copy constructor, you've got to
invoke the copy constructor somehow. Which means having an
object to copy. Which isn't possible with the code you've
given: since you've explicitly declared a constructor, the
compiler will not provide a default constructor, and you have no
other constructor with which to create an object. So you have
no way of creating anything to copy. If you add a
List() {}
to the class, and write:
List<int> kk((List<int>());
, you might get something, but the compiler is allowed to elide
the copy here, so more likely there will be no output. Try:
List<int> a;
List<int> b(a);
Or just put your output in the default constructor.
I know that default constructors initialize objects to their default values, but how do we view these values? If there's a variable of type int, it is supposed to be initialized to 0. But how do we actually view these default values of the constructors? Can anyone please provide a code snippet to demonstrate the same?
Unless specified otherwise, objects are constructed with their default constructor, only if one is available.
And for example ints are not initialized.
This is a common source of huge troubles and bugs, because it can have any value.
So the rule is , always initialise your variables, and for a class you do it in the initialization list
class A
{
private:
int i;
float f;
char * pC;
MyObjectType myObject;
public:
A() : // the initialisation list is after the :
i(0),
f(2.5),
pC(NULL),
myObject("parameter_for_special_constructor")
{}
}
}
In C++, int is not a class and does not have a default (or any other) constructor.
An int is not guaranteed to be initialised to 0.
If you have a class that has an int as an attribute, you should explicitly initialise it in each of the class's constructors (not just the default one).
class sample
{
private:
int x;
public:
sample()
:x(0)
{
}
sample(const int n)
:x(n)
{
}
sample(const sample& other)
:x(other.x)
{
}
// [...]
};
This way you (and users of your class) can "view" the default values.
Good coding practice: write your own constructor, so you know how it will be initialized. This is portable and guaranteed to always have the same behaviour. Your code will be easier to read and the compiler knows how to make that efficient, especially when using the special notation:
class Foo
{
public:
Foo() : i(0), j(0) {}
private:
int i;
int j;
};
AFAIK, if T is a type (not necessarily a class), T() returns a default value for the type T. Here's a small test I ran:
int main()
{
char c = char();
int i = int();
cout << "c = " << hex << (int) c << endl;
cout << "i = " << i << endl;
}
The output is:
c = 0
i = 0
Default constructors do not automatically initialise ints to 0. You can use parentheses to indicate the default value though.
struct X
{
int x;
};
struct X x1; // x1.x is not necessarily 0
struct Y
{
int y;
Y() : y()
{
}
};
struct Y y1; // y1.y will be 0
show your code
And if your int value is a member of class .
you must give it a value in your default constructor func
The default constructor is which can be invoked with 0 parameters. For example
struct X
{
X(int x = 3) //default constructor
{
//...
}
};
It initializes the object to whichever state you code it to initialize. However, if you don't define any constructor at all the compiler will attempt to generate a default constructor for you - which, in turn is equivalent to a constructor with no arguments and no body. That means that all the members of class/struct type will be initialized with their def. ctors and all the members of primitive types like int will remain uninitialized. Please note that I specialy noted that the compiler will attempt to generate a dflt ctor, because it can fail to do so, for example when one or more members of the class do not have default constructors. HTH
AS soon as you have created an object start printing the values such as ob.x.
Thats the only way u can know what default constructor has assigned to the variables.