Calling constant function from another class object - c++

Here is the code that i have
class A
{
public:
void Func1() const;
};
class B
{
public:
A* a;
void Func2() const
{
// do something with 'a'
}
};
void A::Func1() const
{
B b;
b.a = this;
b.Func2();
}
Now obviously this is giving me an error in the line, because I'm trying to convert from const to non-const.
b.a = this;
Is there any way to call Func2 without having to cast away the constness of this. Since Func2 is a const function anyways, it will not change this.

You have to declare the A* as const:
class A
{
public:
void Func1() const;
};
class B
{
public:
const A* a;
void Func2() const
{
// do something with 'a'
}
};
void A::Func1() const
{
B b;
b.a = this;
b.Func2();
}
Since in A::Func1, the this pointer is const.

If class B is always going to work with *a as a const object then as others have said all it takes is to simply change the declaration to
public: const A* a
At this point I should mention that the constness of B::Func2 is a red herring because it has absolutely no relation to the constness of B::a. That B::Func2 is const means that it's not allowed to change the value of a; however, it is allowed to dereference a and mutate the resulting object.
Now, if class B has both const and non-const operations with respect to *a then your class design needs to change. It would be much better if you switched class B to use a const A* a as above, and added another class D : public B that encapsulates all the mutating operations. In addition, a should be hidden behind a property setter; this allows you to do things like
class B {
const A* a;
public:
void setA(const A* a) { this->a = a; }
void Func2() const {}
};
class D : public B {
A* a;
public:
using B::setA;
void setA(A* a) {
this->a = a;
static_cast<B*>(this)->setA(const_cast<const A*>(a));
}
void Func3() { /* do something to D::a */ }
};
With this scheme both B and D keep independent, suitably typed pointers to the object to be accessed. If setA is called on a B, or on a D with a const A* parameter then only B::a is set. If setA is called on a D with an A*, then both B::a and D::a are properly set. This has become possible because by abstracting the member behind a setter you can then overload the setter on the constness of its parameter.

Func2 may not change this, but b.a is not const and you're free to change it afterwards. There's no right way to do this, although workarounds exist, such as mutable or const_cast.
It's the sign of a faulty design.

Yes, make the A * constant:
class B {
public:
const A *a
...
};

Related

C++ cast pointer to base class pointer for virtual method call

I have the following code:
struct A
{
virtual void foo() {std::cout << "A\n";}
};
struct B : public A
{
virtual void foo() {std::cout << "B\n";}
};
void bar(A * a)
{
a->foo();
}
Without changing this code, is it possible to cast bp pointer to B, so calling bar would print "A"?
int main()
{
B * bp = new B();
bar(/* do somethig*/ bp);
return 0;
}
Tried every cast I remebered:
int main()
{
B * bp = new B();
bar((A*)bp);
bar(static_cast<A*>(bp));
bar(reinterpret_cast<A*>(bp));
bar(dynamic_cast<A*>(bp));
return 0;
}
You could make a shim wrapper around B, and have the shim's virtual function dispatched to BWrap::foo() call directly to A::foo();.
There's not really any point in the example to carrying along the B& member variable reference, but for more interesting examples there may be a use case.
struct BWrap : public A
{
B& b;
BWrap(B& bb) : b{bb} {}
virtual void foo() { b.A::foo(); }
};
int main()
{
B* bp = new B();
BWrap bw{*bp};
bar(&bw);
}
If you insist on the A object being a base class subobject of a B object and on not modifying the first code snippet at all, then the only solution is to add an even more derived class that can override the virtual call as explained in the answer by #Eljay (which I completely forgot to think about when first writing this answer).
Other options are to create a complete A object, not a B object, or to modify bar to do a call without virtual dispatch by using a qualified name:
a->A::foo();
All of the casts you are showing have the same effect as the implicit conversion, except for reinterpret_cast which will cause undefined behavior when used this way.

The difference between passing double pointer and pointer as an argument

pass * as a function parameter
#include <iostream>
class A {
public:
A() {}
};
class B : public A{
public:
B() {}
};
void foo(A* a) {
a = new B();
}
void ff() {
A a;
foo(&a);
}
pass ** as a function parameter
#include <iostream>
class A {
public:
A() {}
};
class B : public A{
public:
B() {}
};
void foo(A** a) {
*a = new B();
}
void ff() {
A* a;
foo(&a);
}
When I see leveldb, I am in a puzzle about this.
The specific code is the following.
https://github.com/google/leveldb/blob/master/db/db_impl.cc#L1537
I think it's ok to use FileLock lock
Then pass &lock to LockFile(const std::string& filename, FileLock* lock)
LockFile function is this
Passing double pointer and just a pointer are not the same
void foo(A* a) {
a = new B();
}
Change an input pointer to another value. The result will not reflect in the callee ff().
It's merely change the argument.
void foo(A** a) {
*a = new B();
}
Change a pointer to another pointer and change the value, which is "the another pointer", of this pointer points to . The result will reflect in ff()
According to the ff(), I assume you have a follow up question which need to operate a after foo() is called. So second one might be a proper way.
For FileLock, I believe you're referring to this implementation.
It's using double pointer because it wants to replace the entire content of FileLock.
Live demo
Followup: Why it chose using double pointer instead of pass by reference?
Because reference is not possible to be replaced, my assumption is that it chose it chose to replace the whole content which is simpler than make the implemention complex for re-initialization.

Using smart pointers to keep track of data members that may be deleted

I have two classes A and B. I compute a B deterministically from an A. For each A, I want to keep track of the B with my_B for as long as it exists. Once the B is destructed, I want the my_B to be changed to something like nullptr.
class A{
// stuff
public:
B ComputeB(){
if (my_B is null){
B result = B(A);
my_B = B; // some kind of reference
return B(A);
}
else {
return my_B;
}
}
~A(){ /* Do I need a destructor? */ }
private:
WhatTypeHere my_B;
}
When B is destructed, what will cause my_B to refer to nullptr (or the equivalent for WhatTypeHere)?
Using shared_ptr and weak_ptr
In order to keep your B object alive in A as long as it is still in use, you should have a data member in A of type std::weak_ptr<B> this will allow to access the created B object, as long as it is alive.
The return value from computeB would be std::shared_ptr<B> that would be either acquired from the std::weak_ptr<B> member or created, if the latter is holding nullptr.
Thread safety
The decision whether to create or acquire the existing B shall be thread-safe. For this you shall try to fetch the actual B held by the weak_ptr by using the lock() method, then only if the return value is nullptr create a new one.
The code would look like this:
class A {
// stuff
public:
std::shared_ptr<B> ComputeB() {
std::shared_ptr<B> shared_b = my_B.lock();
if (!shared_b){
shared_b = std::make_shared<B>(*this);
my_B = shared_b;
}
return shared_b;
}
// no need for a destructor, unless "stuff" needs one
// ~A(){}
private:
std::weak_ptr<B> my_B;
};
Copy and assignment
The behavior of above class in copying and assignment is problematic, as the default copy constructor and default assignment operator would perform member-wise copy/assignment, which may result with two different A's holding a weak_ptr to the same B. Most probably this is not what you want, especially not if A is mutable (i.e. can change its inner values).
To present suggested code for copy and assignment, let's assume A holds an int member. The code would then look like this:
class A {
int i;
public:
A(int i1): i(i1) {}
void set(int i1) { i = i1; }
std::shared_ptr<B> ComputeB() {
std::shared_ptr<B> shared_b = my_B.lock();
if (!shared_b){
shared_b = std::make_shared<B>(*this);
my_B = shared_b;
}
return shared_b;
}
A(const A& a): i(a.i) {}
A& operator=(const A& a) { i = a.i; return *this; }
~A() {}
private:
std::weak_ptr<B> my_B;
};
Preserving constness
In the code above, the call to ComputeB() cannot be done on a const A object. If we want to support that we need to have a const version of this function. For matter of semantics I prefer renaming this method (both the const and non-const versions) to getB.
To present suggested code that adds the option for calling getB on a const A object we need to present also an example of class B which is able to hold either a const or non-const reference to A. The code would then look like this:
class A {
int i;
// to prevent code duplication for the const and non-const versions
template<typename AType>
static auto getB(AType&& a) {
std::shared_ptr<B> shared_b = a.my_B.lock();
if (!shared_b){
shared_b = std::make_shared<B>(std::forward<AType>(a));
a.my_B = shared_b;
}
return shared_b;
}
public:
A(int i1): i(i1) {}
void set(int i1) { i = i1; }
std::shared_ptr<B> getB() {
return getB(*this);
}
std::shared_ptr<const B> getB() const {
return getB(*this);
}
A(const A& a): i(a.i) {}
A& operator=(const A& a) { i = a.i; return *this; }
~A() {}
private:
mutable std::weak_ptr<B> my_B;
};
And for B:
class B {
union Owner {
A* const ptr;
const A* const const_ptr;
Owner(A& a): ptr(&a) {}
Owner(const A& a): const_ptr(&a) {}
} owner;
public:
B(A& a): owner(a) {}
B(const A& a): owner(a) {}
const A& getOwner() const {
return *owner.const_ptr;
}
A& getOwner() {
return *owner.ptr;
}
};
On the use of union to manage const and non-const versions of the same pointer, see:
Union of const/non-const Object Pointers
Is const-casting via a union undefined behaviour?
Working example: http://coliru.stacked-crooked.com/a/f696dfcf85890977
Private creation token
The code above allows anybody to create objects of B which may lead to undesired possibilities, like creating a non-const B object via the constructor that gets const A& a, resulting with a potential casting from const to non-const when calling getOwner().
A good solution might be to block the creation of B and allow it only from class A. Since the creation is done via make_shared putting B's constructors in the private section of B with a friend declaration for A wouldn't help, it is not A that is calling new B it is make_shared. So we go for a private token approach as in the following code:
class A {
int i;
// only authorized entities can create B
class B_PrivateCreationToken {};
friend class B;
template<typename AType>
static auto getB(AType&& a) {
std::shared_ptr<B> shared_b = a.my_B.lock();
if (!shared_b){
shared_b = std::make_shared<B> (
std::forward<AType>(a),
B_PrivateCreationToken{} );
a.my_B = shared_b;
}
return shared_b;
}
public:
// public part as in above version...
private:
mutable std::weak_ptr<B> my_B;
};
And for B:
class B {
union Owner {
A* const ptr;
const A* const const_ptr;
Owner(A& a): ptr(&a) {}
Owner(const A& a): const_ptr(&a) {}
} owner;
public:
B(A& a, A::B_PrivateCreationToken): owner(a) {}
B(const A& a, A::B_PrivateCreationToken): owner(a) {}
// getOwner methods as in above version...
};
Code: http://coliru.stacked-crooked.com/a/f656a3992d666e1e
You can return a std::shared_ptr from ComputeB(), and make my_B a std::weak_ptr. Something like this:
std::shared_ptr<B> ComputeB() {
if (my_B.expired()) {
auto result = std::make_shared<B>(*this);
my_B = result;
return result;
} else {
return std::shared_ptr<B>(my_B);
}
}
private:
std::weak_ptr<B> my_B;
The idea is that any caller of ComputeB becomes the partial owner of the B instance, which means that it will only be destroyed when all shared_ptrs to it are destroyed. The purpose of the weak_ptr is to point to the B instance without owning it, so the lifetime isn't tied to the A instance at all

Lifetime of dependent classses in C++?

I have a class A that provides methods to construct instances of class B. And B holds a private reference to A and provides a constructor to set this reference.
class A {
public:
B* construct_B ();
}
class B {
private:
const A& private_A;
public:
B ( const A& my_A ): private_A (my_A) { }
}
The implementation of construct_B takes care of dynamic allocation and passing the reference to itself via this.
How do I implement this setup in such a way that I make sure that the lifetime of A is longer than B so that its reference remains valid? Notice that I don't care about all the possibilities of construct_B instead of returning a raw pointer I could return a smart pointer or similar.
One possible way of solving this could be having B instead of holding a reference to hold a smart pointer to A, and instead of dynamically allocating B in construct_B to take a static reference to B and then set it's pointer, something like
class A :
public std::enable_shared_from_this<A> {
public:
void setup_B ( const B& my_B ) {
my_B.set_A (shared_ptr_from_this() ) ;
}
class B {
private:
const shared_ptr<A> private_A_ptr;
public:
void set_A ( const shared_ptr<A> my_A ):
private_A_ptr (my_A) { }
}
which then could be implemented by
int main () {
A static_A;
B static_B;
A.setup_B (static_B);
}
Does the shared_ptr of this last construction avoid the problem of A being deleted before B?
shared_ptr is your answer. Something like this:
#include <memory>
struct A;
class B {
const std::shared_ptr<A> private_A_ptr;
public:
B(std::shared_ptr<A> parent) : private_A_ptr(std::move(parent)) {}
};
struct A :
std::enable_shared_from_this<A>
{
B make_b() {
return B(shared_from_this());
}
};
int main()
{
// this would be invalid:
//A a;
//auto b = a.make_b();
// but this is fine
auto pa = std::make_shared<A>();
auto b = pa->make_b();
// later...
pa.reset();
// A still exists because ownership was shared with b
}

How to return a const ref to a struct object such that all its nested structures also are read only?

How do I prevent all the member variables in a nested struct to be non modifiable?
typedef struct A
{
int a;
int b;
}A1;
typedef struct B
{
A1* objA;
}B1;
class C
{
public:
const B& GetB() const { return objB; }
PopulateB();
private:
B objB;
};
int main()
{
C objC;
objC.PopulateB();
const B& objB2 = objC.GetB();
objB2.objA->a = 3; // compiler allows this
}
I just want a struct that is completely read only and I expected this to work. (In this case objB2)
The pointer is const. The data it points to is not. Thats just how pointers work The best solution is to not expose raw pointers. A non-const accessor function would not be allowed on a const reference, so you can avoid the tricky indirection.
As an aside, you don't have to typedef structs like that. It's a C-ism.
The pointer type in your struct B refers to a non-const value, and this is the definition that counts. If you wanted to control access, you should hide data members and provide accessors and mutators:
struct B
{
private:
A1* objA;
public:
A1 & a1() {return *objA;}
A1 const & a1() const {return *objA;}
};
You can try:
typedef struct B
{
const A1& objA;
}B1;