问题
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 namespace
s 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