How do I call a template constructor whith objects of another class?
Example:
#include <iostream>
using namespace std;
class RGB{
private:
int _R;
int _G;
int _B;
public:
RGB(int a, int b, int c){
_R=a;
_G=b;
_B=c;
}
};
class Gray{
int _G;
public:
Gray(int x){
_G=x;
}
};
template <class T1, class T2>
class Pixel{
public:
Pixel(T1 i, T2 j, int a, int b){
foo=i;
bar=j;
x=a;
y=b;
}
void setPixel(T1 a, T2 b){
foo=a;
bar=b;
}
void getPixel();
private:
int x;
int y;
T1 foo;
T2 bar;
};
int main(){
Gray g(3);
RGB rgb(4, 5, 6);
Pixel<Gray,RGB> pi(g, rgb, 10,27);
return 0;
}
I can use the constructor of the class only with the default constructors of the two classes Bar1 and Bar2 but not with the two objects of the classes that I have created before(in this case bar1 and bar2).
Errors are:
main.cpp: In instantiation of 'Pixel::Pixel(T1, T2, int, int) [with T1 = Gray; T2 = RGB]':
main.cpp:62:37: required from here
main.cpp:35:37: error: no matching function for call to 'Gray::Gray()'
main.cpp:35:37: note: candidates are:
main.cpp:26:5: note: Gray::Gray(int)
main.cpp:26:5: note: candidate expects 1 argument, 0 provided
main.cpp:23:7: note: Gray::Gray(const Gray&)
main.cpp:23:7: note: candidate expects 1 argument, 0 provided
main.cpp:35:37: error: no matching function for call to 'RGB::RGB()'
main.cpp:35:37: note: candidates are:
main.cpp:16:9: note: RGB::RGB(int, int, int)
main.cpp:16:9: note: candidate expects 3 arguments, 0 provided
main.cpp:9:7: note: RGB::RGB(const RGB&)
main.cpp:9:7: note: candidate expects 1 argument, 0 provided
The errors go away if I add default values to the RGB and Gray constructors.
Sorry for the mess, I'm new here...
You need to learn about initialization lists:
Pixel(T1 i, T2 j, int a, int b) : x(a), y(b), foo(i), bar(j) {
}
foo=i;, etc. in the body of the Pixel constructor is assigning to an already existing object. When your Pixel constructor is called, it trys to call the default constructor for its subobjects, Gray and RGB, however, both those types do not have default constructors generated since you provide a user-defined constructor. The solution is to use initialization lists to initialize the subobjects in your Pixel class.
Also, note that subobjects of the class are constructed in the order they are declared inside the class definition, so you should always initialize them in the same order as they are declared in your constructor initialization list.
Related
class Q
{
Q(const Q &obj) {} // copy constructor
Q& operator= (const Q& a){} // equal op overload
}
template <class T>
class B{
public : T x;
B<T>(T t) {
// x = t; }
}
int main()
{
Q a(2);
a.init(1,0);
a.init(2,1);
B <Q> aa(a); // this line gives error
}
How to initialize template class with copy constructor? B aa(a); // this line gives error
I want to solve it but I could not.
Error:
no matching function for call to 'Q::Q()'|
candidate: Q::Q(const Q&)|
candidate expects 1 argument, 0 provided|
candidate: Q::Q(int)|
candidate expects 1 argument, 0 provided|
To solve the mentioned error just add a default constructor inside class Q as shown below
class Q
{
Q() //default constructor
{
//some code here if needed
}
//other members as before
};
The default constructor is needed because when your write :
B <Q> aa(a);
then the template paramter T is deduced to be of type Q and since you have
T x;
inside the class template B, it tries to use the default constructor of type T which is nothing but Q in this case , so this is why you need default constructor for Q.
Second note that your copy constructor should have a return statement which it currently do not have.
Below C++ code works.
#include<iostream>
using namespace std;
class Complex{
private:
int real, imag;
public:
Complex(int r=0, int i=0){
real = r; imag = i;
}
};
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3;
}
When the parameterized constructor's variables r and i are uninitialized(eg: Complex(int r, int i)), the compiler throws up the error
main.cpp:19:13: error: no matching function for call to ‘Complex::Complex()’
19 | Complex c3;
| ^~
main.cpp:10:5: note: candidate: ‘Complex::Complex(int, int)’
10 | Complex(int r, int i){
| ^~~~~~~.
I understood this to be an issue with the statement Complex c3;. Pardon me for being naive, but it's unclear why it works this way in the initial code snippet itself. Hope someone can clarify this.
The Complex constructor you show, with default arguments, can be called with two, one or zero arguments. If no arguments is used then the default values will be used.
But if you remove the default values, you no longer have a default constructor, a constructor that can be used without arguments.
It's really exactly the same as normal functions with default argument values...
Lets say you have this function:
void foo(int arg = 0)
{
// Implementation is irrelevant
}
Now this can be called as:
foo(123); // Pass an explicit argument
Or as:
foo(); // Equivalent to foo(0)
If you remove the default value:
void foo(int arg)
{
// Implementation is irrelevant
}
Then calling the function without any argument is wrong:
foo(); // Error: Argument expected
The definition Complex(int r=0, int i=0) allows for 0, 1 or 2 parameters. Complex c3; is constructing a Complex with 0 parameters.
You could instead have overloads, e.g.
class Complex{
private:
int real, imag;
public:
Complex() : real(0), imag(0) {}
Complex(int r, int i) : real(r), imag(i) {}
};
Note that it is better to use the member initialisers than assignment statements in the body of the constructor.
In the following code, I want to use the default constructor {.data = value}, because I want my class to be POD. I don't understand the error message I get on compilation (llvm or gnu, c++11):
#include <type_traits>
class a {
char data;
static inline a create(char c) { return {.data = c}; } // this fails
static inline a create2(char c) { a x; x.data = c; return x; } // this is OK
public:
void init(char c) { *this = create(c); }
};
int main() {
a s;
s.init('x');
return std::is_pod<a>::value;
}
with error message
t.cc:5:43: error: no matching constructor for initialization of 'a'
static inline a create(char c) { return {.data = c}; }
^~~~~~~~~~~
t.cc:3:7: note: candidate constructor (the implicit copy constructor) not viable: cannot convert
argument of incomplete type 'void' to 'const a &'
Can some kind soul explain to me why the type of a is incomplete when I want to use it, and why it's treated as void?
You cannot aggregate initialize a private member.
From https://en.cppreference.com/w/cpp/language/aggregate_initialization
An aggregate is one of the following types: ... class type (typically, struct or union), that has no private or protected non-static data members
Since a is a class, not a struct, data is private.
Declare data to be public, or declare the type to be a struct to default it to public.
Then replace static inline a create(char c) { return {.data = c}; }
with static inline a create(char c) { return a { c }; }
per https://en.cppreference.com/w/cpp/language/list_initialization
direct-list-initialization (2)
I have this code:
i receive next error: A::A(int) candidate expect 1 argument, 0 provided but I cannot understand what the problem is.
#include <iostream>
using namespace std;
class A
{
int x;
public:
A(int i):x(i) {}
int get_x() const {return x;}
};
class B:public A
{
int *y;
public:
B(int i):A(i) {y=new int[i]; for(int j=0;j<i;j++) y[j]=1;}
B(B&);
int &operator[] (int i) {return y[i];}
};
B::B(B&a)
{
y=new int[a.get_x()];
for(int i=0;i<a.get_x();i++) y[i]=a[i];
}
ostream& operator<<(ostream& o, B a)
{
for(int i=0;i<a.get_x();i++) o<<a[i];
return o;
}
int main()
{
B b(5);
cout<<b;
return 0;
}
Because A does not have a constructor that takes 0 arguments you need to explicitly call the constructor with arguments provided from any class constructor that inherits from A, which is B in this case.
In your first constructor:
B(int i):A(i) {y=new int[i]; for(int j=0;j<i;j++) y[j]=1;}
You are doing this well by calling A(i).
But in your second constructor:
B::B(B&a)
{
y=new int[a.get_x()];
for(int i=0;i<a.get_x();i++) y[i]=a[i];
}
There is no call to A's constructor and thus you get an error since the compiler doesn't know how to create an A object, you probably meant to do :
B::B(B&a) : A(a.get_x())
{
y=new int[a.get_x()];
for(int i=0;i<a.get_x();i++) y[i]=a[i];
}
Your second B constructor B::B(B&a) implicitly tries to construct the base class A using its default constructor, which is not defined.
You may explicitly call the A(int) constructor, i.e.:
B::B(B&a)
: A(a.get_x())
{
...
The problem is that when you declare an object of type B you also sort need to construct an instance of A.
In B::B(B&a) you do not explicitly call any constructor for A, so the compiler try to call the one with no parameters A::A(), but it fails since it is not declared.
You have to either declare a A::A() in A or explicitly call one of the available constructors in A from B's constructror.
Note that A::A() could be automatically generated by the compiler, and is called default constructor. Read more about it here
I'm trying to write a template class that doesn't have default constructor.
For A<int> works fine, but for A<A<int>> I don't know how to get it to work.
1 #include <iostream>
2 using namespace std;
3
4 template <typename T>
5 class A {
6 T x;
7
8 public:
9 A(T y) { x = y; }
10 };
11
12 int main() {
13 A<int> a(0);
14 A<A<int> > b(A<int>(0));
15
16 return 0;
17 }
Error list from clang
test.cpp:9:5: error: constructor for 'A<A<int> >' must explicitly initialize the member 'x' which does not have a default constructor
A(T y) { x = y; }
^
test.cpp:14:16: note: in instantiation of member function 'A<A<int> >::A' requested here
A<A<int> > b(A<int>(0));
^
test.cpp:6:7: note: member is declared here
T x;
^
test.cpp:5:9: note: 'A<int>' declared here
class A {
^
You are not properly constructing x in the initializer list of the constructor, hence A(T y) must default construct x before invoking operator= to copy assign y to it.
int provides a default constructor, which just let the value uninitialized, but A<int> does not.
Your constructor should be
A(T y) : x(y) { }