I have two questions relating to classes. I have run into a problem in using classes in multi-file programs. Here are three example files which illustrate the problem I am having and the errors I am getting.

file1.cpp

//file1.cpp
#include<iostream>
#include"file3.h"

using std::cout;
using std::cin;

namespace baz
{
    extern MyClass foobar;
}

int main()
{
    baz::foobar.setFOO();
    
    baz::foobar.bar();
    cout << *baz::foobar.FOO << "\n";
    
    cin.ignore();
    
    return 0;
}

/*errors:
         
         In function `main':
                     [Linker error] undefined refference to `baz::foobar'
                     [Linker error] undefined refference to `MyClass::setFOO()'
                     [Linker error] undefined refference to `baz::foobar'
                     [Linker error] undefined refference to `MyClass::bar()'
                     [Linker error] undefined refference to `baz::foobar'
         Id returned 1 exit status
*/

file2.c

//file2.c

#include"file3.h"

namespace baz
{
    MyClass foobar;
}

void baz::foobar.bar(void)
{
     foo = 42;
}

void baz::foobar.setFOO(void)
{
     FOO = &foo;     
}

file3.h

//file3.h

class MyClass
{
      private:
      int foo;
      
      public:      
      void bar(void);
      void setFOO(void);
      int * FOO;
};

What I was wanting this program to do was display 42 and wait for [Enter] to be pressed; however, it will not compile. As far as I can tell the main program needs to see a function prototype, but if I place

void baz::foobar.bar(void);
void baz::foobar.setFOO(void);

in file3.h then file3.h gets an error! How should I make a prototype?

My other question is how I would be able to get rid of the setFOO() function and say something like

const int & FOO = foo;

inside the class definition. My compiler says this is not allowed. I want FOO to be visible globaly and to reflect the contents of foo but be unmodifiable.

Thanks in advance. :)

Dani AI

Generated

Good catch by : your undefined reference errors came from declaring baz::foobar without providing a single definition the linker could see, and from not linking all translation units into one project. One more gotcha: naming a C++ source file file2.c often makes IDEs compile it as C, which will not understand C++ namespaces or member definitions. Rename it to .cpp and ensure all three files are in the same project and being linked.

For a clean multifile layout, declare the object in the header and define it once in a .cpp. Also prefer read-only accessors over exposing raw pointers.

Header (add this to your existing header):

namespace baz {
  class MyClass;          // if needed
  extern MyClass foobar;  // declaration only (no storage)
}

Implementation (in exactly one .cpp):

#include "file3.h"

namespace baz {
  MyClass foobar; // single definition with storage
}

Instead of a public int* FOO plus a setFOO(), make the member private and expose a const view. For example, add a const accessor to your class (keeps callers from modifying the value):

// inside class MyClass
public:
  const int& FOO() const { return foo; }  // read-only reference to the private member

Use it like this:

std::cout << baz::foobar.FOO() << '\n';

If you truly want a global read-only alias, declare it in the header and define it in the same .cpp that defines foobar so initialization order is well-defined:

// file3.h
namespace baz {
  extern const int& FOO;  // global, read-only view
}

// file2.cpp
#include "file3.h"
namespace baz {
  MyClass foobar;                // object lives here
  const int& FOO = foobar.FOO(); // bind after foobar exists
}

Note: you cannot write const int& FOO = foo; inside the class body; reference data members must be bound in a constructor initializer list, which is why an accessor or the TU-level alias above is safer.

Recommended Answers

All 9 Replies

Foo is an undefined variable. Use other words instead of foo or FOO.

Are you saying that in the baz::foobar.bar() function I should say

baz::foobar.foo = 42;

I did say

int foo;
...
const int * FOO;

inside MyClass, so foo and FOO should exist.

Some things got messed up it should be like this:

main.cpp

//file1.cpp
#include<iostream>
#include"file3.h"

using std::cout;
using std::cin;

namespace baz
{
    extern MyClass foobar;
}

int main()
{
    baz::foobar.setFOO();
    
    baz::foobar.bar();
    cout << *baz::foobar.FOO << "\n";
    
    cin.ignore();
    
    return 0;
}
//file3.h

namespace baz{

class MyClass
{
      private:
      int foo;
      
      public:      
      void bar(void);
      void setFOO(void);
      int * FOO;
};

}
//file2.c

#include"file3.h"

namespace baz
{
    MyClass foobar;

    void MyClass::bar(void)
    {
         foo = 42;
    }

    void MyClass::setFOO(void)
    {
         FOO = &foo;     
    }

}

:icon_redface: oops! The changes you made to file2.cpp made it so file 2.cpp compiles with no errors, but file1.cpp still has the same errors. (This is my first attempt at classes so I am sorry about the simple errors.)

hmm, it compiles without problems with gcc.

How do you compile it?

It works! :icon_biggrin: I am using Dev-C++. I would have compiled it with g++ on my linux computer but, it bit the dust a while back. I just got a win XP computer and put Dev-C++ on it. The problem was with my lack of knowledge of Dev-C++. I didn't have all three files properly put into a project file. Thank you for your help! :)
I just read about classes yesterday and I am really eager to try them out. Can anyone tell me why this code doesn't work?

class baz
{
  private:
  int foo;

  public:
  const int & FOO = foo;
}

I want to make it so that everyone can see what is in foo via FOO but, only foo is modifiable.

You have to initilialize the FOO in constructor, FOO is a reference and has to initialize in contructor

class baz
{
  private:
  int foo;

  public:
  const int & FOO;
  baz() : FOO(foo) {} // constructor
 ~baz(){ } // destructor

};

Thanks for all of your help!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.