How to use two constructors? - c++

I have a code like this.
#include <iostream>
#include <vector>
using namespace std;
class AbstractValueC{
private:
long age = 0;
int abs;
bool spec = false;
public:
AbstractValueC() {
abs = 0;
}
AbstractValueC(int& a, bool b = false){
abs = *a;
spec = b;
}
AbstractValueC(int a, bool b = false){
abs = a;
spec = b;
}
int get_value() const {
return abs;
}
long get_age(){
return age;
}
};
int main(){
vector<AbstractValueC> v;
int init = 1;
int next = 2;
v.push_back(AbstractValueC(std::move(init)));
cout << "I have created first v element." << endl;
v.push_back(AbstractValueC(std::move(next)));
cout << "I have created second v element." << endl;
std::vector<AbstractValueC> result;
for (auto a : v) {
int pre = a.get_value();
result.push_back(AbstractValueC(pre));
}
cout << "I have created result." << endl;
return 0;
}
Please tell me how to solve the error of
invalid type argument of unary ‘*’ (have ‘int’)
abs = *a;
^
and the error
call of overloaded ‘AbstractValueC(int&)’ is ambiguous
result.push_back(AbstractValueC(pre));
^
I actually have a custom type (Abs) in place of int for the abs member in my actual code. Also the requirement is that I cannot call the default constructor of Abs in main. I can use abs = Abs::null;. So please suggest a solution that avoid calling the default constructor for Abs if I replace int with Abs in the class definition.

invalid type argument of unary ‘*’ (have ‘int’)
AbstractValueC(int& a, bool b = false){
abs = *a;
spec = b;
}
Argument a is an int reference, not a pointer, so you can't dereference as *a.
The code should be abs = a;
call of overloaded ‘AbstractValueC(int&)’ is ambiguous
As #strom points out in the comments, you have 2 similar constructors:
AbstractValueC(int& a, bool b = false)
AbstractValueC(int a, bool b = false)
Which the compiler cannot readily distinguish between. You should get rid of one of them.

The real problem is that you are using two constructors with the same signature :
How does the compiler choose between using :
AbstractValueC v=AbstractValueC(value);//int constructor
And
AbstractValueC v=AbstractValueC(value);//reference constructor
When you have
Int value = 0;//for example
To get rid of this error(ambigueous constructor call) you could either change one of the constructors or replace your reference constructor with a pointer constructor
To change the constructor to a pointer, you need to create a value pointer in your class and create a contructor:
// in class declaration
Int *pointerValue = nullptr;
AbstractValueC(int* pointer, bool b = false);
// implementation
AbstractValueC::AbstractValueC(Int *pointer, bool b=false) {
pointerValue=pointer;
}

Related

Convert object function to function pointer

I'm trying convert a object function to function pointer but can't get it, i've done something like this, simple example:
typedef struct
{
int v1;
int DoSome(int a)
{
return v1 * a;
}
} strx;
int main()
{
strx a; // instance...
a.v1 = 2;
std::function<int(strx* instance, int value)> DoSome = std::mem_fn(&strx::DoSome);
cout << DoSome(&a, 4) << endl; // 16 ok
int(*pDoSome)(strx* instance, int value) = (int(*)(strx*, int))std::mem_fn(&strx::DoSome); // syntax error
// ptr method...
pDoSome(&a ,4);
return 0;
}
and i have obtained something like:
main.cpp [Error] invalid cast from type 'std::_Mem_fn' to type 'int ()(strx, int)'
How i can do correctly the casting?
You can't. This is why std::function is more flexible than pointers to functions.
How i can do correctly the casting?
You cannot. Object pointers and function pointers are totally different concepts. Only nullptr can be used to initialize both types of pointers. Otherwise, they are not guaranteed to be compatible.
I suggest sticking with the std::function.
If you must have a function pointer, you have to use a non-member function or a static member function of a class.
E.g.
int doSomeFunction(strx* instance, int value)
{
// Use instance any way you please.
// ...
//
return 0;
}
int main()
{
strx a; // instance...
a.v1 = 2;
int(*pDoSome)(strx* instance, int value) = doSomeFunction;
// ptr method...
pDoSome(&a ,4);
return 0;
}

Class non-static method pointer to global function

I'm trying to point a class method to a global function, i've seen this
but how i can't do it without instance?.
Consider this:
class x
{
public:
int(x::*GetVal)(int);
};
int RtX(int a)
{
return a * 4;
}
// declaration
int(x::*GetVal)(int) = (int(x::*)(int))&::Rtx; // :: global? // error
int main()
{
x a;
cout << (a.*GetVal)(4) << endl;
}
This returns me the error:
[Error] invalid cast from type 'int ()(int)' to type 'int
(x::)(int)'
x::GetX is a pointer to member. These are deeply complicated beasts, and you can't get them to point to non-member functions. The following code will work:
#include <iostream>
int RtX(int a) // Global non-member function
{
return a * 4;
}
class x
{
public:
int(x::*GetVal)(int);
// This is an instance member function which acts as a proxy and calls the
// the global function
int RtX(int a) { return ::RtX(a); }
};
int main()
{
x a;
a.GetVal =&x.RtX; // Assign the member variable. Could do this in the
// constructor. **NOTE** No casts!
std::cout << (a.*GetVal)(4) << std::endl;
}
If you find yourself reaching for a cast when dealing with function pointers and pointers-to-member-functions, stop - you are almost certainly doing it wrong, and while it will compile, it is very likely not to run properly.
Alternatively, as noted in the comments, use std::function.
#include <iostream>
#include <functional>
int RtX(int a)
{
return a * 4;
}
class x
{
public:
std::function<int(int)> GetVal;
// Initialize GetVal in the constructor.
x() : GetVal(RtX)
{}
// Alternatively, you can initialize the variable in with a default
// initialization. You can also declare the member const if you don't want to
// change it later.
const std::function<int(int)> gv = RtX;
/*
};
int main()
{
x a;
std::cout << a.GetVal(4) << std::endl;
}
Non static member functions need an instance in order to be called. You might consider using a static function member instead and if you also use std::function, you might get a simple code to assign your member function without instance:
#include <iostream>
#include <functional>
int RtX(int a)
{
return a * 4;
}
class x
{
public:
static std::function<int(int)> GetVal;
};
std::function<int(int)> x::GetVal = RtX;
int main()
{
x a;
std::cout << (a.GetVal)(4) << std::endl;
}

Why is the default parameter value of the overloaded base class value chosen, instead of the default specified in the executed derived method

I've noticed a strange thing while playing with logical shift. Here's my code:
#include <iostream>
using namespace std;
class C
{
public:
virtual int shift(int n = 2) const { return n << 2; }
};
class D
: public C
{
public:
int shift(int n = 1) const { return n << 5; }
};
int main()
{
const D d;
const C *c = &d;
cout << c->shift() << endl;
return 0;
}
The programme returns 64, so it takes value n = 2 from the class C and the function's body from class D.
It works fine after removing const from functions but I don't understand why. Can someone help me ?
Default argument values are based on the static type (the type known at compile time).
The choice of virtual function implementation is governed by the object's most derived type at run time, the dynamic type.

How to initialize the reference member variable of a class?

Consider the following code C++:
#include<iostream>
using namespace std;
class Test {
int &t;
public:
Test (int &x) { t = x; }
int getT() { return t; }
};
int main()
{
int x = 20;
Test t1(x);
cout << t1.getT() << " ";
x = 30;
cout << t1.getT() << endl;
return 0;
}
It is showing the following error while using gcc compiler
est.cpp: In constructor ‘Test::Test(int&)’:
est.cpp:8:5: error: uninitialized reference member ‘Test::t’ [-fpermissive]
Why doesn't the compiler directly call the Constructor?
That is because references can only be initialized in the initializer list. Use
Test (int &x) : t(x) {}
To explain: The reference can only be set once, the place where this happens is the initializer list. After that is done, you can not set the reference, but only assign values to the referenced instance. Your code means, you tried to assign something to a referenced instance but the reference was never initialized, hence it's not referencing any instance of int and you get the error.
My compiler emits this error:
error C2758: 'Test::t' : must be initialized in constructor base/member initializer list
And that's exactly what you must do. References must be initialized in the initializer list:
#include<iostream>
using namespace std;
class Test {
int &t;
public:
Test (int &x) : t(x) { } // <-- initializer list used, empty body now
int getT() { return t; }
};
int main()
{
int x = 20;
Test t1(x);
cout << t1.getT() << " ";
x = 30;
cout << t1.getT() << endl;
return 0;
}
Explanation:
If the reference is not in the initiliazer list, it's next to impossible for the compiler to detect if the reference is initialized. References must be initialized. Imagine this scenario:
Test (int &x, bool b)
{
if( b ) t = x;
}
Now it would be up to the caller of the constructor to decide if valid code was generated. That cannot be. The compiler must make sure the reference is initialized at compile time.

What exactly is the ->* operator?

I've never used it before and just stumbled upon it in an article... I thought it would be the equivalent to *x->y but apparently it isn't.
Here's what I tried, and gave me an error:
struct cake {
int * yogurt;
} * pie;
int main(void) {
pie = new cake;
pie->yogurt = new int;
return pie->*yogurt = 4;
}
Its used when you have pointers to member functions.
When you have a pointer to a function of a class, you call it in much the same way you would call any member function
object.membername( ... )
or
objectptr->membername( ... )
but when you have a member function pointer, an extra * is needed after the . or -> in order that the compiler understand that what comes next is a variable, not the actual name of the function to call.
Here's an example of how its used.
class Duck
{
public:
void quack() { cout << "quack" << endl; }
void waddle() { cout << "waddle" << endl; }
};
typedef void (Duck::*ActionPointer)();
ActionPointer myaction = &Duck::quack;
void takeDuckAction()
{
Duck myduck;
Duck *myduckptr = &myduck;
(myduck.*myaction)();
(myduckptr->*myaction)();
}
It defines a pointer to a member.
In an expression containing the –>* operator, the first operand must
be of the type "pointer to the class type" of the type specified in
the second operand, or it must be of a type unambiguously derived from
that class.
MSDN
Pointer-to-Member Operators: .* and ->*
The .* and ->* operators will point to member functions of a class or structure. The code below will show a simple example of how to use the .* operator, if you change the line:
Value funcPtr = &Foo::One; to Value funcPtr = &Foo::Two; the result displayed will change to 1000 since that function is inValue*2
for example Taken From Here:
#include <iostream>
#include <stdlib.h>
class Foo {
public:
double One( long inVal ) { return inVal*1; }
double Two( long inVal ) { return inVal*2; }
};
typedef double (Foo::*Value)(long inVal);
int main( int argc, char **argv ) {
Value funcPtr = &Foo::One;
Foo foo;
double result = (foo.*funcPtr)(500);
std::cout << result << std::endl;
system("pause");
return 0;
}