0

[UPDATE] a reproducible example

By splitting declaration and definition into different files, my toy code built without problem...

my main.cpp

#include <iostream>
#include "file0.h"
#include "file1.h"
#include "file2.h"

int main() {
    test a;
    double b = a.get_recipocal(2.0);
    double c = a.get_sqrt(2.0);
    std::cout << "b = " << b << std::endl;
    std::cout << "c = " << c << std::endl;
    return 0;
}

my file0.h

#ifndef TEST_MULTI_FILES_FILE0_H
#define TEST_MULTI_FILES_FILE0_H

class test {
private:
    double a;
public:
    double get_recipocal(int a);
    double get_sqrt(int a);
};


#endif//TEST_MULTI_FILES_FILE0_H

my file1.h

#ifndef TEST_MULTI_FILES_FILE1_H
#define TEST_MULTI_FILES_FILE1_H

double test::get_recipocal(int a) {
    return 1. / a;
}

#endif//TEST_MULTI_FILES_FILE1_H

my file2.h

#include <cmath>
#ifndef TEST_MULTI_FILES_FILE2_H
#define TEST_MULTI_FILES_FILE2_H

double test::get_sqrt(int a) {
    return sqrt(a);
}

#endif//TEST_MULTI_FILES_FILE2_H

Built and run without problem. So it is not an obvious error in my production code

Thanks!

(below are original question) I am new to C++ classes, here is my problem

for example, I have a class in file b0.h

class B::virtual public A {
  void func1() {
    some work1;
  }
  void func2() {
    some work2;
  }
  ...
};

Now I want to move the implementation of func2() into an other header file, say b1.h so I did the following:

#include "path/to/b0.h"
void B::func2(){
  some work2;
}

But the compiler will complain

use of undeclared identifier 'B'
void B::func2() {
     ^ 

(I also tested the following: in b0.h, I included b1.h and if I made func2() in b1.h a static function, I can call it from b0.h without problem.)

The goal is to separate members of B into two header files, each one contain one function implementation (I want to have a side-by-side comparison between func1 and func2 in different file, they are similar and very long). I feel this is a very common scenario, but I didn't find a good example. Is there an obvious mistake? Thank you!

  • 1
    I don't think your example code is enough to spot the error that is shown. Although your code you have 2 definitions for func2() – drescherjm Jul 22 '20 at 14:39
  • 4
    Why are you implementing the class members in a header file instead of a translation unit / source file? – drescherjm Jul 22 '20 at 14:41
  • @ drescherjm This is unclear to me but the whole package is in such a fashion so I think that's ok. –  Jul 22 '20 at 14:46
  • 2
    `class B::virtual public A {` should be `class B : virtual public A {`. And your functions need return type and the header should only contain declarations (without a function body). Definitions go to a source file. All of this is explained in more detail in some [good C++ books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – Lukas-T Jul 22 '20 at 14:46
  • Oh sorry that's a typo.. should be : . But even I only contained declaration in this header file, I still got the same error –  Jul 22 '20 at 14:54
  • Please post a [mcve]. – n. m. could be an AI Jul 22 '20 at 14:56
  • 1
    It is possible to do what you're asking, but it is bad design. If the whole package is in that fashion, it's still bad design and you ought not to follow it. – Beta Jul 22 '20 at 15:00
  • @Beta Thanks for the advice. But If I only have declaration in this header file, the class me is still red (unclear identifier). –  Jul 22 '20 at 16:07

1 Answers1

1

What you want to do is quite common if you have larger classes. What you need is one header file with all the declarations, say b.h:

#include "path/to/a.h"

class B : virtual public A { // : instead of :: 
  void func1(); // return type, no function body
  void func2(); // return type, no function body
};

Then you can split the definitions (the actual implementation) over as many source files as you wish. For example file b_func1.cpp might contain the definition for B::func1

#include "path/to/b.h"

void B::func1() { /* some code */ }

And file b_func2.cpp might contain the definition for B::func2

#include "path/to/b.h"

void B::func2() { /* some code */ }

Anyway, only in specific cases (like templates or inline functions) the definition can be in a header. It may work as long as you include every header only once, but it's still wrong, so put the definitions in a translation unit / source file.

Lukas-T
  • 11,133
  • 3
  • 20
  • 30
  • 1
    @yue Maybe you have a circular include which you are not showing in your example code. It's not very clear where that error comes from given the current example code. – drescherjm Jul 22 '20 at 15:12
  • @yue looking at the other snippets you posted, you probably need some clarification about include. Those snippets only work because a) you include them in the correct order, such that the declarations come before the definitions and b) you include every file just once. But that's no good project structure, will cause too many pitfalls. Don't put any definitions in headers (unless you need to, as already mentioned, but you don't need to do this here.) The working of those snippets is balanced on a razors edge and it wont work like this for any real code base. – Lukas-T Jul 22 '20 at 16:50