How to implement a wrapper around C 'objects' using smart pointers?

百般思念 提交于 2020-08-08 06:32:39

问题


I am using a C library which uses raw pointers from C++. Therefore, I'm looking into wrapping all the pointers to C objects in C++ classes and turning them into smart pointers. I've built a working example:

#include <iostream>
using namespace std;

// the C library is oop: using structs and naming conventions. Like this: 

// C library declarations
struct Animal_s {
    int age;
};
typedef struct Animal_s Animal;

Animal* make_animal(int age);

void free_animal(Animal* animal);

Animal* do_something_with_animal(Animal* animal);



// C lib implementations
Animal* make_animal(int age ){
    auto* animal = (Animal*) malloc(sizeof(Animal));
    animal->age = age;
    return animal;
}

void free_animal(Animal *animal){
    free(animal);
}

Animal* do_something_with_animal(Animal* animal){
    //...
    return animal;
}



// C++ wrapper 
class AnimalWrapper{
    Animal* animal_; // how to use smart pointers? 

public:
    explicit AnimalWrapper(int age){
        animal_ = make_animal(age);
    };

    ~AnimalWrapper(){
        free_animal(animal_);
    }

    AnimalWrapper(const AnimalWrapper& animalWrapper){
        if (this != &animalWrapper){
            animal_ = animalWrapper.animal_;
        }
    }

    AnimalWrapper(AnimalWrapper&& animalWrapper) noexcept {
        if (this != &animalWrapper){
            animal_ = animalWrapper.animal_;
        }
    }
    AnimalWrapper& operator=(const AnimalWrapper& animalWrapper)  {
        if (this != &animalWrapper){
            animal_ = animalWrapper.animal_;
        }
        return *this;
    }

    AnimalWrapper& operator=(AnimalWrapper&& animalWrapper) noexcept {
        if (this != &animalWrapper){
            animal_ = animalWrapper.animal_;
        }
        return *this;
    }

    Animal *getAnimal() const {
        return animal_;
    }

    Animal* doSomethingWithAnimal(){
        return do_something_with_animal(animal_);
    }
};



int main(){

    AnimalWrapper animalWrapper(6);


    return 0;
};

This example works and according to valgrind, mangages the memory correctly. However, is it possible to implement the wrapper class using smart pointers? Or must I manually manage the memory in the wrapper classes?


回答1:


You can use std::unique_ptr for managing lifetime of Animal objects:

#include <memory>

struct FreeAnimal {
    void operator()(Animal* a) const noexcept {
        free_animal(a);
    }
};

using AnimalPtr = std::unique_ptr<Animal, FreeAnimal>;

int main() {
    AnimalPtr party_animal{make_animal(21)};

    do_something_with_animal(&*party_animal);
    // or
    do_something_with_animal(party_animal.get());
}



回答2:


You cannot use any C++ issue in C. What you are doing is using C code with a C++ compiler, as C doesn't support something like

using namespace something;

In general, if you pass a pointer to something that has not been declared extern "C" you'll run into trouble.

You are seriously confused by using C constructs against C++. If you declare a struct A there's no need to typedef struct A A; because that's implicit in C++. But that cannot be C, because you use namespaces in your source code....

to use a C library in your code, you need to declare (in C++ only) as extern "C" or the linker will have serious trouble finding it (due to the name mangling C++ does to identifiers to support overloading)

I cannot guess you you can get a complete compilation in this situation.



来源:https://stackoverflow.com/questions/61850433/how-to-implement-a-wrapper-around-c-objects-using-smart-pointers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!