1

I read a program which defines two classes in two header files as below:

file IM.h:

class SM;

class IM
{
public:
    void print_IM() const {
        std::cout << "IM called" << std::endl;
    }
    void print_SM(const SM& s) const {
        s.print_SM();
    }
};

file SM.h:

class IM;

class SM
{
public:
    SM(IM* p_) :p(p_) {};
    void print_SM() const {
        std::cout << "SM called" << std::endl;
    }
    void print_IM() const {
        p->print_IM();
    }

private:
    IM* p = NULL;
};

The IM class has a function "print_SM" which takes SM as an argument, while SM class has a pointer to IM as a private data member.

This program doesn't compile on my machine (VS2019). The error message says "used undefined class SM". I'm also very confused about this "cross definition", where one contains the other. But a similar program comes from a library of my professor...

Is this a valid program? any way to improve it to satisfy the attempt ?

pphero0287
  • 47
  • 1
  • 8
  • See this related question with answers: https://stackoverflow.com/q/553682/509868 – anatolyg Jul 19 '21 at 11:34
  • You could have separate `IM.cpp` and `SM.cpp` files with the implementation of the methods, and include `SM.h` and `IM.h` respectively from there. I would also add `#pragma once` at the start of the header files. – rturrado Jul 19 '21 at 11:41

1 Answers1

3

When s is a reference to incomplete type, s.print_SM is no good. The same about p and p->print_IM.

To make it work, move the implementation of the methods to a dedicated cpp-file. Leave the declarations in the h-file, where they should be.

// im.h
class IM
{
public:
    void print_SM(const SM& s) const;
};

// im.cpp
#include "im.h"
#include "sm.h"

...

void IM::print_SM(const SM& s) const {
    s.print_SM();
}

Do this transformation to both your classes. You can get away with moving only one, but it may be a bit tricky, and may break later while you develop your code. So start by separating interface (*.h) from implementation (*.cpp).


You should include both h-files in each of the cpp-files (see code above). In fact, it is these #includes that solve your problem. The separation into h and cpp files is just an intermediate step needed to make this solution valid (i.e. prevent circular #include).

anatolyg
  • 26,506
  • 9
  • 60
  • 134
  • my compiler says "doesn't allow to use incomplete class SM" in the im.cpp file. Without the cpp file, the declaration works fine now. – pphero0287 Jul 19 '21 at 11:58