4

I have some code on C++.

Bird.h

class Bird
{
    std::string s;
    static int i;
public:
    Bird();

    ~Bird();
    friend std::ostream& operator<<(std::ostream& os, Bird& b);

};

Bird.cpp

#include <iostream>
#include <sstream> 
#include "Bird.h"



Bird::Bird()
{
    ++i;
    std::stringstream ss;
    ss<<"Bird#";
    ss<<i;
    s = ss.str();
}
Bird::~Bird()
{
    i--;
}
std::ostream& operator<<(std::ostream& os, Bird& b)
{
    const char* chr = (b.s).c_str();
    return os << chr << std::endl;
}

Main.cpp

#include <iostream>
#include <sstream> 
#include "Bird.h"


int Bird::i=0;

int main()
{
    Bird b();
    std::cout << b;
}

I am getting the following error:

Main.obj : error LNK2019: unresolved external symbol "class Bird __cdecl b(void)" (?b@@YA?AVBird@@XZ) referenced in function _main

But if I create Bird b; it's OK. What can I do?

Sathish
  • 3,740
  • 1
  • 17
  • 28
imladris
  • 565
  • 2
  • 5
  • 9
  • Show us the command you are using to compile this, probably you are not sending `Bird.cpp` to the compiler. – Pacha Dec 23 '13 at 08:14

6 Answers6

4

You meant to write Bird b; to create a Bird object.

Bird b() is a function (called b, taking no parameters and returning a Bird), which you haven't implemented.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
1
Bird b();

This means that b is a function that takes no parameters and returns a Bird. You then try to output the value of this function, but the function doesn't exist. Perhaps you want:

Bird b;

This says that b is a Bird that should be default constructed.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
1

This is a case of C++'s "Most Vexing Parse."

The C++ compiler thinks you're declaring a function named b that returns a Bird and then trying to print a pointer to it, as opposed to default-constructing an instance of Bird. The linker then complains that there's no function named b that returns a Bird. That is what this error message tries to tell you:

error LNK2019: unresolved external symbol "class Bird __cdecl b(void)" 

The Most Vexing Parse happens due to a syntactic ambiguity in the C++ language. The ambiguity exists because the syntax for a constructor invocation looks much like the syntax for a function prototype.

The ambiguity that was resolved in a way guaranteed to generate StackOverflow questions that kept some tenuous backward compatibility with C, at the expense of the otherwise obvious meaning in a C++ program.

In this case, because your Bird is default-constructed, you can simply remove the parentheses and be done. If you needed to call a different constructor, then the advice at the Wikipedia article linked above may help.

If you can use C++11, you can use the brace-initializer syntax to make it always unambiguous:

Bird b{};             // Use this if default constructed
Bird b{ ..args.. };   // Use this if you need to invoke a particular constructor

The Most Vexing Parse is a surprisingly rich topic. Google it and read and read and read if you're truly curious.

Joe Z
  • 17,413
  • 3
  • 28
  • 39
1

The linker error is triggered by this

Bird b();

This is a function declaration of a function called b, returning a Bird by value. You then use the function here:

std::cout << b;

and the linker cannot find its implementation. You need

Bird b;   // C++03 and C++11
Bird b{}; // C++11

Furthermore, you should consider defining Bird::i in Bird.cpp, not main.cpp.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
1

try this:

int main()
{
    Bird b;
    std::cout << b;
}

the default constructor doesn't need '()'

C0reFast
  • 11
  • 1
0

If nothing else seems to work, check if your file path does not contain special characters. This suddenly became a problem for me after adding an extra source file.

chris544
  • 889
  • 2
  • 10
  • 21