// A mixin is used through inheritance, but it’s not really useful to // consider it an is-a relation. Instead, think of the mixin as // granting abilities to the derived class, like a magic wand. #include // mkstemp() #include // cout #include #include // close() #include using namespace std; // A mixin that creates & destroys a temporary file // It provides the method tempname(), which returns // a C++ string which contains the full path to the temporary file. class Tempfile { protected: // These methods are protected, so they appear as private methods in // the derived class. The ctors & dtor are protected, so this mixin // can’t be instantiated by itself. Tempfile(const string &prefix = "temp") // default prefix argument : name("/tmp/" + prefix + "-XXXXXX"), // pattern for name fd(mkstemp(name.data())) { // Create & open the file. } ~Tempfile() { close(fd); remove(name.data()); } // What does it mean to allow copying? Do we share the temporary // file, or copy any data it contains into a new temporary file, // or what? Until we resolve this problem, forbid copying. Tempfile(const Tempfile &) = delete; Tempfile& operator=(const Tempfile &) = delete; const string &tempname() const { return name; // Return read-only reference to read/write string. } private: string name; // name of temporary file, accessible to derived class const int fd; // Linux file descriptor of open temporary file }; class Foo : public Tempfile { public: // Foo() : Tempfile("corgi") { } void show() { cout << "My temporary file name is " << tempname() << '\n'; // Note that I didn’t have to say Tempfile::tempname(). // I simply used the inherited method. } }; int main() { Foo f; f.show(); // Tempfile t; // fails, why? // cout << f.tempname(); // fails, why? return 0; }