The difference between passing double pointer and pointer as an argument - c++

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.

Related

Can a parent class which is reinterpreted as a child class use the child's functions in its functions?

I want to call the child's function from parent's function in reinterpreted class, like below.
Example
#include <iostream>
class A {
public:
void func1() {
// some code
func2();
// some code
}
protected:
virtual void func2() {
printf("class A\n");
}
};
class B : public A {
protected:
virtual void func2() {
printf("class B\n");
}
};
int main() {
A* ab = new A();
ab->func1(); // this print "class A"
B* bab = reinterpret_cast<B*>(ab);
bab->func1(); // this also print "class A"
// I want to print "class B" when I use bab->func1()
}
In this situation, Is there any way to print class B using the reinterpreted class bab without redefining func1?
For C++ polymorphism to kick in, you must create an instance of the derived class somewhere, but you can store a pointer to the base class. Using the base-class pointer will dispatch to the overridden functions of the derived class. So your definition of A and B is fine, your usage in the main function is not. reinterpret_cast is not intended for this.
#include <iostream>
#include <memory>
class A {
public:
void func1() {
// some code
func2();
// some code
}
protected:
virtual void func2() {
printf("class A\n");
}
};
class B : public A {
protected:
virtual void func2() {
printf("class B\n");
}
};
int main() {
{
// This works, but don't do this. Naked "new" is not modern C++ and dangerous.
A* ab = new B();
ab->func1();
delete ab;
}
{
// VARIANT 2: use smart pointers
std::unique_ptr<A> ab = std::make_unique<B>();
ab->func1();
}
{
// VARIANT 3: A non-smart pointer is okay, as long as it
// 1. references an existing allocated object
// 2. the pointer does not outlive the object it points to
B b;
A* ab = &b;
ab->func1();
}
{
// VARIANT 4: Like Variant 3, but with reference instead of pointer
B b;
A& ab = b;
ab.func1();
}
}
Output
class B
class B
class B
class B
https://godbolt.org/z/8e5E85nx5
EDIT: Try to avoid allocation with new. Any memory allocated in this fashion must be freed by you using delete and it is very easy to forget (I did when I first wrote this answer, kinda proving my point). Even if you do delete the memory at the end of your function, there is the possibility that your code never reaches this statement, e.g. if exceptions are thrown somewhere between new and delete.Here is some further reading:
Why is it a bad idea to use 'new'?
Why should C++ programmers minimize use of 'new'?

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.

Why can "template<class T> void f(T& t)" override functions in T but "template<class T> void f(T t)" cannot?

I have a class A with child class B, and want to make a template function to call virtual functions of A and B:
#include <stdio.h>
class A{
public:
virtual void test(){
printf("A\n");
}
};
class B:public A{
public:
virtual void test(){
printf("B\n");
}
};
template<class T>
void f(T t){
t.test();
}
int main(){
A* a=new B();
f<A>(*a);
return 0;
};
it prints A only and seems does not override test(), but when I change
void f(T t)
to
void f(T& t)
like that:
#include <stdio.h>
class A{
public:
virtual void test(){
printf("A\n");
}
};
class B:public A{
public:
virtual void test(){
printf("B\n");
}
};
template<class T>
void f(T& t){
t.test();
}
int main(){
A* a=new B();
f<A>(*a);
return 0;
};
,it prints B, why would that happen?
When you use
template<class T>
void f(T t){ ... }
your code suffers from object slicing. You construct a B but only the A part of the object gets passed to f.
That does not happen when you use
template<class T>
void f(T& t){ ... }
Over-riding is achieved by using Pointers or References. Please do read a good article regarding polymorphism.
Happy coding.
When you call f(T t), c++ actually new an object of T by constructor T(T& t). Then the reference of this object is passed into function.
You call write code to prove it
class A {
public:
int x;
A():x(6){
}
A(A& a) {
x = 2;
}
virtual void test() {
printf("%d\n", x);
}
};
class B : public A {
public:
virtual void test() {
printf("%d\n", x);
}
};
void fun(A a)
{
a.test();
}
void f(A& a)
{
a.test();
}
int main(void)
{
A* a = new A();
A* b = new B();
A* c = new A(*b);
fun(*a);
fun(*b);
f(*a);
f(*b);
f(*c);
}
the output is 2 2 6 6 2
How you have your class hierarchy defined is that class B is derived from class A. So when class B's constructor is called it must call A's constructor first before it can be constructed. Both A & B have the same exact virtual function or definition called test().
With your first implementation of f() your template will deduce the parameter type while it is being compiled. It is looking for a class type where in main when you invoke the template function you are telling this template function to expect a type of class A. This will then use A::test() to call the test function. In your main function before you invoke f() you are creating a pointer of type class A dynamically and placing it in the heap, but you are using B's constructor which is a derived type of A. This will use B's constructor to call A's constructor. Your template function is expecting type A so it is invoking a.test() or A::test() in your code.
In your second declaration or definition of f() your classes are defined the same and behave the exact same way. What is different this time is your template function that will be resolved during compilation to deduce its parameter's type. In this version of the function it is expecting the address of class type A since now that it is expecting a memory address as opposed to the actual variable itself, this time when you instantiate or invoke the function f() where it expects a parameter of type T& it is now using the referencing capabilities of c++ and it now invokes b.test().
If you want to see why this is happening use your first declaration of f() and set a break point where you have A* a = new B(); and step into the code line by line, don't step over, but into. Then do the same exact process with your second version of f() and you will see what is happening.
This isn't because the class is or isn't overriding the virtual function; this is due to how template functions work.
Now my question is why would you want to create a pointer for a base type and setting new memory for it by calling its derived type's constructor.
Normally with polymorphism and abstract classes you would usually create a type of derived but you may have a container that holds pointers to the base class of derived where you would normally cast them dynamically. For example let us say that you have a base class of Automobile which is abstract; meaning you can not create this class directly because it's constructor is protected where only derived types can have access to it. Now a derived type might be Car, Van, Truck, SUV, Jeep, MotorCycle and in some other class or function you may have a vector<shared_ptr<Automobile>> stored. So this way you can push a smart pointer of a truck, a car, and a van, all into the same container by dynamically casting these constructed objects pointers to their Base type Automobile since they all publicly inherit from them! However when working with abstract types special care needs to be used.
Check out this little program to see how polymorphism works (there are no abstract types here)
#include <conio.h>
#include <string>
#include <iostream>
#include <vector>
#include <memory>
class Base {
public:
Base() {}
virtual ~Base(){}
virtual void test() const { std::cout << "Base" << std::endl; }
};
class DerivedA : public Base {
public:
DerivedA() : Base() {}
virtual ~DerivedA() {}
virtual void test() const override { std::cout << "DerivedA" << std::endl; }
};
class DerivedB : public Base {
public:
DerivedB() : Base() {}
virtual ~DerivedB() {}
virtual void test() const override { std::cout << "DerivedB" << std::endl; }
};
template<class T>
void f( T t ) {
t.test();
}
template<class T>
void g( T& t ) {
t.test();
}
int main() {
DerivedA* a = new DerivedA();
//f<DerivedA>( *a );
//g<DerivedA>( *a );
DerivedB* b = new DerivedB();
//f<DerivedB>( *b );
//g<DerivedB>( *b );
std::vector<Base*> vBases;
vBases.push_back( a );
vBases.push_back( b );
for ( unsigned i = 0; i < vBases.size(); ++i ) {
if ( i == 0 ) {
std::cout << "First Iteration: i = " << i << std::endl;
} else if ( i == 1 ) {
std::cout << "Second Iteration: i = " << i << std::endl;
}
f<DerivedA>( *dynamic_cast<DerivedA*>( vBases[i] ) );
f<DerivedB>( *dynamic_cast<DerivedB*>( vBases[i] ) );
std::cout << std::endl;
g<DerivedA>( *static_cast<DerivedA*>( vBases[i] ) );
g<DerivedB>( *static_cast<DerivedB*>( vBases[i] ) );
std::cout << std::endl;
}
delete a; // You Forgot To Delete Your Dynamic Pointers - Memory Leak!
delete b;
std::cout << "Press any key to quit" << std::endl;
_getch();
return 0;
}
Output
DerivedA
DerivedB
DerivedA
DerivedA
DerivedA
DerivedB
DerivedB
DerivedB
Maybe this will help you to understand what is happening with your two different template types by using a dynamic_cast<> for f<>() your first version of your template function and using static_cast<> for g<>() for your second version of your template function that takes a reference instead of a stack copy of a variable.
If you remember there are two elements in this vector the first being a DerivedA* and the second being a DerivedB* both which are of a type Base and are stored as a Base* in the vector. The first 4 lines of out put is work that is done on the first element of our vector only! The last 4 lines of out put is work that is done on the second element of our vector only!
Our first stored element at index 0 is of a DerivedA type stored as a Base* and the first call to f<>() we dynamically cast it to a DerivedA* type and we then dereference the pointer. The second call to f<>() we do the same thing except we dynamically cast it to a DerivedB* type and deference it. So here this first stored object is invoking DerivedA::test() then it is invoking DerivedB::test() by using the dynamic cast.
The next two lines are still working on the same element which is our DerivedA* stored as a Base*at index 0 in our vector. This time we are now using g<>() your second method of your function template, and instead of using a dynamic_cast<> we are now using a static_cast<> since g<>() is expecting a reference to an object and not a stack variable itself. If you notice this time around nothing gets casted from one type to another and our function template is always invoking DerivedA::test() even though on the second call to this method we are telling it to cast it to a <DerivedB> type.
For the next 4 lines of output we are now working with our 2nd stored object in the vector at index 1 but this time our saved object is of a DerivedB type stored as a Base*. On the next two lines we have the same output as in the first iteration. This time DerivedB is being casted to a DerivedA for the first call to f<>() and remains its own type for the second call to f<>() and for the final two lines as you can see the stored object at index 1 that is of a DerivedB type stored as a Base* is not being changed or casted to a DerivedA type on the first call of g<>().

How can I accept multiple classes for one function argument?

Say I have two classes, ClassA and ClassB.
ClassB inherits ClassA, and has some additional functions and variables.
Is it possible for me to make a function that can accept either ClassA or ClassB as the same argument, and let me determine which one was used?
Yes, you can take the parameter by reference:
void foo(ClassA& x) //or const ClassA
You'll be able to pass both instances of ClassA or ClassB, and use RTTI to determine which type it actually is inside the function.
Alternatively, you can pass a pointer to ClassA, but references are to be preferred where possible.
Declare the function parameter to be a pointer or a reference to an ClassA instance (don't pass it by value or the input instance will get sliced at runtime). Then you can use dynamic_cast if you need to access ClassB-specific functionality. For example:
class ClassA
{
public:
int a;
virtual ~ClassA() {}
void DoSomething();
};
class ClassB : public ClassA
{
public:
int b;
void DoSomethingElse();
};
void func(ClassA *obj)
{
int a = obj->a;
obj->DoSomething();
ClassB *objB = dynamic_cast<ClassB*>(obj);
if (objB)
{
int b = objB->b;
objB->DoSomethingElse();
}
}
int main()
{
ClassA a;
func(&a);
ClassB b;
func(&b);
return 0;
}
Here's an idea with a bit of indirection. The function Consumer::accept accepts both objects of type A and type B, and the specific behaviour is implemented by those classes rather than by your consumer.
struct Consumer;
struct A
{
virtual ~A() { }
virtual int use(Consumer &);
};
struct B : A
{
virtual int use(Consumer &);
};
struct Consumer
{
void accept(A & x)
{
int n = x.use(*this);
do_more_stuff(n);
}
void do_more_stuff(int);
// ...
};

Calling constant function from another class object

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
...
};