Implicit conversion insists on using private function - c++

I have a class that has a conversion operator to int& that I want to hide. I created a derived class that only offers a conversion to int and made the conversion to int& private. But I still cannot make the int conversion to be used, either the compiler tells me that the conversion is ambiguous, or insists to use the int& conversion and tells me it is inaccessible. How do I make this work?
struct Base {
int value;
operator int&() { return value; }
};
struct Derived : Base {
operator int() { return operator int&(); }
private:
using Base::operator int&;
};
int main() {
int p = Derived();
}
P.S. The compiler uses gcc 9.3.0, and the real case is the wrapping of XmlRpc::XmlRpcValue class from ROS to handle probable conversion from double XmlRpcValue type to int or int XmlRpcValue type to double.

I could not find a way through inheritance. But if containment is an option (Derived has a Base instead of is a), it is much simpler:
struct Base {
int value;
operator int&() { return value; }
};
struct Derived{
Base b;
operator int() { return b.operator int&(); }
};
int main() {
int p = Derived();
}
The main drawback is that you will have to use explicit delegation for the methods/members you want to offer in Derived

Related

Return class object with member variable

Why the function test() works even I'm not returning a Base class ? What happens with the compilation ? Can someone explain me ?
#include <iostream>
class Base {
public:
Base(){}
Base(int val): _val(val){};
~Base(){};
Base test(int n){
return (n);
}
int &operator *() { return (_val); };
private:
int _val;
};
int main()
{
Base base;
Base a;
a = base.test(42);
std::cout << *a << std::endl;
return (0);
}
You declared a constructor that takes in an int, and you declared that test(int n) should always return a Base class. The compiler knows that in order to create a Base object you need either nothing (default constructor) or an int, so it creates an object using the constructor that takes an int an returns that.
If you wanted to, you could be explicit about it and do something like the following and get the exact same behaviour:
Base test(int n){
return Base(n);
}
In short, n is implicitly cast to a Base object, as you declared a constructor that requires only an int.

Const and non-const version and inheritance

In my problem, I will have a few classes that will share getters and setters (in my case, the operator()). Suppose I have the following
class Base
{
public:
int& operator()() { return value; }
int operator()() const { return value; }
protected:
int value;
};
class Derived : public Base
{
public:
int operator()() const { return value; }
};
I expected being able to do something like this :
Derived d;
d() = 1;
but the compiler complains saying that the expression is not assignable. However, doing this
Derived d;
d.Base::operator()() = 1;
works correctly. Why is that ? Shouldn't the compiler be able to look up for the member function in the base class ? Is there a solution to avoid rewriting the non-const method is the derived class ?
Shouldn't the compiler be able to look up for the member function in the base class?
Yes, it is possible, but you have to be explicit. For that you can use a using declaration, which introduces the operator to the derived class:
class Derived : public Base
{
public:
using Base::operator();
int operator()() const { return value; }
};

I'm confused about inheritance of conversion operator

Consider following program: (See live demo here.)
#include <iostream>
class Base
{
int s{9};
public:
operator int()
{
return s;
}
};
class Derived : public Base
{
int s{18};
};
int main()
{
Base b;
int s=b;
std::cout<<s<<'\n';
Derived d;
int m=d;
std::cout<<m;
}
Output of program is:
9
9
Here, the conversion operator of Base class is inherited, so the initialization of m variable is valid.
But now I want to print the value of s data member that belongs to Derived. How can I do this?
Is it necessary to rewrite conversion operator for derived class also? Can't I reuse the same Base class conversion operator?
Your s parameter of Base is shadowed in Derived, but since conversion operator in in Base class, Base::s is used inside it.
You can do this:
class Base
{
int s{9};
public:
Base() {}
Base(int v) : s(v) {}
operator int()
{
return s;
}
};
class Derived : public Base
{
public:
Derived() : Base(18)
{
}
};
or write its own conversion operator in Derived.

Assign base class pointer to derived class without using dynamic cast

In this given piece of code,i am trying to assign base class pointer to derived class pointer (downcasting) without using dynamic cast.Using help of assignment operator.
#include<iostream>
using namespace std;
class A
{
int i;
public:
A& operator =( const A& b)
{
i = b.i;
return *this ;
}
};
class B:public A
{
int j;
public:
B& operator =( const B& c)
{
A::operator=(c);
j=c.j;
return *this ;
}
};
int main()
{
A *a;
B *b;
b=a;
return 0;
}
It shows error: invalid conversion of A* to B*.
You have to cast it by dynamic_cast or static_cast(be careful of UB in this case) ...
In C++, run-time type checking is implemented through dynamic_cast.
Compile-time downcasting is implemented by static_cast, but this
operation performs no type check. If it is used improperly, it could
produce undefined behavior [1].
and your assignment operators will not help.

does assignment operator work with different types of objects?

class A {
public:
void operator=(const B &in);
private:
int a;
};
class B {
private:
int c;
}
sorry. there happened an error. is assignment operator valid ? or is there any way to achieve this? [There is no relation between A and B class.]
void A::operator=(const B& in)
{
a = in.c;
}
Thanks a lot.
Yes you can do so.
#include <iostream>
using namespace std;
class B {
public:
B() : y(1) {}
int getY() const { return y; }
private:
int y;
};
class A {
public:
A() : x(0) {}
void operator=(const B &in) {
x = in.getY();
}
void display() { cout << x << endl; }
private:
int x;
};
int main() {
A a;
B b;
a = b;
a.display();
}
This isn't an answer, but one should be aware that the typical idiom for the assignment operator is to have it return a reference to the object type (rather than void) and to return (*this) at the end. This way, you can chain the assignent, as in a = b = c:
A& operator=(const A& other)
{
// manage any deep copy issues here
return *this;
}
Both assignment operator and parameterized constructors can have parameters of any type and use these parameters' values any way they want to initialize the object.
Others have clued in on this, but I'll actually state it. Yes you can use different types, but note that unless you use friend, your class cannot access the private members of the class it's being passed in with the operator.
Meaning A wouldn't be able to access B::c because it's private.