I have a file A.cpp which has the following lines:
#include"B.h"
int main(int argc, char **argv)
{
...
char *input_file = *argv;
B *definition = new B(input_file);
...
}
In B.h, I have the following:
class B
{
public:
// Constructors
B(void);
B(const char *filename);
...
}
When I compile, I get the following error: undefined reference to 'B::B(char const*)'
Any suggestions on how to fix?
Thanks.
You need a definition for B::B(char const *). You have provided only a declaration for B::B(char const *), and the Linker is complaining that it can't actually find that function.
It seems like you specified the header for the function, but never actually wrote the body of the function.
You need to define the function I.E.
B::B(const char *filename){
// Do stuff
}
in B.cpp.
Your problem doesn't have anything to do with const correctness.
Related
Why does the ASSERT_EQ below cause an undefined reference to Bar::kBar error?
To compile: g++ a.cc -lgtest -lpthread
#include <gtest/gtest.h>
class Bar {
public:
static const size_t kBar = 0;
};
TEST(Basic, Basic) {
ASSERT_EQ(0, Bar::kBar);
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
From the Googletest FAQ:
The compiler complains about "undefined references" to some static const member
variables, but I did define them in the class body.
If your class has a static data member:
// foo.h
class Foo {
...
static const int kBar = 100;
};
You also need to define it outside of the class body in foo.cc:
const int Foo::kBar; // No initializer here.
Otherwise your code is invalid C++, and may break in unexpected ways.
In particular, using it in Google Test comparison assertions (EXPECT_EQ, etc)
will generate an "undefined reference" linker error.
This explanation is rather enigmatic. (Why is it "invalid C++?") That is
probably because a satisfactory explanation is rather technical.
Even though your class bar declares the static data member kBar with
an initializer, that does not suffice to provide the data member with a
definition that has external linkage (i.e. that the linker can see), and
without one any code that attempts to odr-use1 Bar::kBar will
encounter an undefined reference linkage error. This can be illustrated
without involving Googletest:
foobar.cpp
#include <cstdlib>
class Bar {
public:
static const std::size_t kBar = 0;
};
bool foo(std::size_t const & k)
{
return k == 0;
}
int main()
{
return foo(Bar::kBar);
}
Try to build:
$ g++ foobar.cpp
/tmp/ccWaEsDu.o: In function `main':
foobar.cpp:(.text+0x1c): undefined reference to `Bar::kBar'
collect2: error: ld returned 1 exit status
The solution is as per the FAQ:
#include <gtest/gtest.h>
class Bar {
public:
static const size_t kBar = 0;
};
const size_t Bar::kBar;
TEST(Basic, Basic) {
ASSERT_EQ(0, Bar::kBar);
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
As of C++17 you will be able to omit the out-of-class definition if
you prefix the initialized in-class declaration with inline (which
will make it a definition).
[1] [ODR-use](http://en.cppreference.com/w/cpp/language/definition)
>Informally, an object is odr-used if its address is taken, or a reference is
>bound to it, and a function is odr-used if a function call to it is made or its
>address is taken. If an object or a function is odr-used, its definition must
>exist somewhere in the program; a violation of that is a link-time error.
I am creating an Apache2 module and experiencing a weird compilation problem.
This is prototype of my function used to parse config command named "analytics_ip":
static const char *apr_cfg_set_analytics_ip(cmd_parms *cmd, void *config, const char *data);
This is array of command_rec structures containing pointers to this function:
static const command_rec apr_cmds[] =
{
AP_INIT_TAKE1("analytics_ip", apr_cfg_set_analytics_ip, NULL, OR_ALL, ""),
{ NULL }
};
Structure command_rec is declared in header file http_config.h
typedef struct command_struct command_rec;
struct command_struct {
/** Name of this command */
const char *name;
/** The function to be called when this directive is parsed */
cmd_func func;
/** Extra data, for functions which implement multiple commands... */
void *cmd_data;
/** What overrides need to be allowed to enable this command. */
int req_override;
/** What the command expects as arguments */
enum cmd_how args_how;
/** 'usage' message, in case of syntax errors */
const char *errmsg;
};
When I follow cmd_func, it gets to the following declaration:
typedef const char *(*cmd_func) ();
If I am not mistaken, this means "pointer to function returning pointer to char and not accepting any arguments". How can this be possible? Command parsing function has to accept at least one parameter containing a module value of config variable corresponding to that function.
I am using g++ to compile this module.
Error message:
mod_xxx.h:65:2: error: invalid conversion from ‘const char* (*)(cmd_parms*, void*, const char*) {aka const char* (*)(cmd_parms_struct*, void*, const char*)}’ to ‘cmd_func {aka const char* (*)()}’ [-fpermissive]
};
Thanks in advance
cmd_func is a union, it is defined in http_config.h as follows:
typedef union {
/** function to call for a no-args */
const char *(*no_args) (cmd_parms *parms, void *mconfig);
/** function to call for a raw-args */
const char *(*raw_args) (cmd_parms *parms, void *mconfig,
const char *args);
/** function to call for a argv/argc */
const char *(*take_argv) (cmd_parms *parms, void *mconfig,
int argc, char *const argv[]);
/** function to call for a take1 */
const char *(*take1) (cmd_parms *parms, void *mconfig, const char *w);
/** function to call for a take2 */
const char *(*take2) (cmd_parms *parms, void *mconfig, const char *w,
const char *w2);
/** function to call for a take3 */
const char *(*take3) (cmd_parms *parms, void *mconfig, const char *w,
const char *w2, const char *w3);
/** function to call for a flag */
const char *(*flag) (cmd_parms *parms, void *mconfig, int on);
} cmd_func;
enum cmd_how args_how; is responsible for choosing the correct version of the function.
The switch handling it is located in server/config.c (in the invoke_cmd function).
You seem to be using the "take1" version which corresponds to cmd->AP_TAKE1 or simply cmd->take1.
The problem might be that C and C++ have differences regarding the union initialization. (AP_INIT_TAKE1 uses the { .take1=func } syntax which doesn't work in C++).
You'll have to initialize static const command_rec apr_cmds in a C++-compatible way or move it to a separate object file compiled with C. Or if you're not using C++ then simply compile with gcc.
For the project I'm working on we ended up adding a cast to allow the compilation to complete successfully, and the code seems to work OK as it correctly reads in the values specified in the configuration file. Here's the extract of this practice:
extern "C" {
static const command_rec kiwix_settings[] =
{
AP_INIT_TAKE1("zimFile", (const char* (*)())kiwix_set_zimfilename, NULL, RSRC_CONF, "The ZIM filename in full including the extension"),
AP_INIT_TAKE1("zimPath", (const char* (*)())kiwix_set_path, NULL, RSRC_CONF, "The path to the ZIM file, including the trailing //"),
{ NULL }
};
}
The full file (and indeed the project) are opensourced. Here's the link to the full file https://github.com/kiwix/kiwix-apache/blob/master/mod_kiwix.cpp
PS: thanks for your question and https://stackoverflow.com/users/257568/artemgr's answer as they helped me and another volunteer to work out how to resolve the problem for our project.
I'm working on an optimisation project and have decided to try threads to increase the speed of my code. the format of the code is:
Main.cpp:
int main(int argc, char **argv) {
B *b = new B(argv[1]);
b->foo();
delete b;
return EXIT_SUCCESS;
}
B.cpp:
#include B.hpp
B::B(const char *filename) { .... }
B::task1(){ /*nop*/ }
void B::foo() const {
boost::thread td(task1);
td.join();
}
B.hpp:
#include <boost/thread.hpp>
class B{
public:
void task1();
void foo();
}
however when I try to compile this code, I get an error at boost::thread td(task1), saying:
error: no matching function for call to 'boost::thread::thread(<unresolved overloaded function type>)'
not entirely sure what the problem is and I've tried hacking away to no success. Any help is appreciated!
edit: new error
B.o: In function 'B::b() const':
B.cpp:(.text+0x7eb): undefined reference to 'vtable for boost::detail::thread_data_base'
B.cpp:(.text+0x998): undefined reference to 'boost::thread::start_thread()'
B.cpp:(.text+0x9a2): undefined reference to 'boost::thread::join()'
B.cpp:(.text+0xa0b): undefined reference to 'boost::thread::~thread()'
B.cpp:(.text+0xb32): undefined reference to 'boost::thread::~thread()'
B.o: In function 'boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::cmf0<void, B>, boost::_bi::list1<boost::_bi::value<B const*> > > >::~thread_data()':
B.cpp:(.text._ZN5boost6detail11thread_dataINS_3_bi6bind_tIvNS_4_mfi4cmf0Iv4BEENS2_5list1INS2_5valueIPKS6_EEEEEEED2Ev[_ZN5boost6detail11thread_dataINS_3_bi6bind_tIvNS_4_mfi4cmf0Iv4BEENS2_5list1INS2_5valueIPKS6_EEEEEEED5Ev]+0x8): undefined reference to 'boost::detail::thread_data_base::~thread_data_base()'
B::task() is a member function, so it takes an implicit first parameter of type B*. So you need to pass an instance to it in order to use it in a boost::thread.
void B::foo() const {
boost::thread td(&B::task1, this); // this is a const B*: requires task1() to be const.
td.join();
}
But since B::foo() is a const method, you would have to make B::task1() a const method too:
class B {
void task1() const:
}
Anyone knows how to compile this example code under msvc2010 ? (supposedly compiles under GCC)
class cmdLine;
struct cmdList
{
const char *c;
const char *s;
const char *h;
void (cmdLine::*cmdFuncPtr)();
};
class cmdLine
{
public:
cmdLine();
static cmdList myCmdList[];
void test();
};
cmdLine::cmdLine()
{
}
void cmdLine::test()
{
}
cmdList cmdLine::myCmdList[] =
{
{"xxx", "yyy", "zzzzz", &cmdLine::test},
{"aaa", "bbb", "ccc", 0}
};
int _tmain(int argc, _TCHAR* argv[])
{
cmdLine c;
(c.myCmdList[0].*cmdFuncPtr) (); //error (why?)
}
I get error C2065: 'cmdFuncPtr' : undeclared identifier and dont know whats wrong ?
Use this syntax
(c.*c.myCmdList[0].cmdFuncPtr) ();
As cmdFuncPtr is a pointer to a method of cmdLine, it needs an instance of the class to be invoked on, which is c. At the same time, cmdFuncPtr is a member of cmdList, so it needs an instance of the class where it is stored, which is c.myCmdList[0]. That's why c shall be used twice in the expression.
The expression presented by OP parses as: "Invoke a method on an instance of a class in c.myCmdList[0] through a method pointer stored in a standalone variable cmdFuncPtr". Such variable doesn't exist, that's what the compiler complains about.
Using the following code:
#include <stdio.h>
struct my_struct {
int a;
int b;
my_struct();
};
my_struct::my_struct(void)
{
printf("constructor\n");
}
void my_struct(void)
{
printf("standard function\n");
}
int main (int argc, char *argv[])
{
struct my_struct s;
s.a = 1;
s.b = 2;
printf("%d-%d\n", s.a, s.b);
return 0;
}
I get a warning compiling with g++ -Wshadow main.cpp:
main.cpp:15:20: warning: ‘void my_struct()’ hides constructor for ‘struct my_struct’
I would be ok with that warning if the void my_struct function actually replaced the my_struct::my_struct one. But it does not appears to be the case. If I run the program, I get:
constructor
1-2
Any idea what this warning mean ? It is quite annoying especially when I include C headers into C++ code
The warning points out that the my_struct() function has the same name as the my_struct structure. It means you will be unable to write:
my_struct s; // Error.
Because the compiler will think that you're using a function as a type. However, as you probably realized, you can still instantiate your structure with the struct keyword:
struct my_struct s; // Valid.
void my_struct(void) has the same name of your class/struct and since it is in the global namespace it is conflicting with your class/struct's constructor.
You could try something like:
#include <cstdio>
struct my_struct {
int a;
int b;
my_struct();
};
my_struct::my_struct(void)
{
printf("constructor\n");
}
namespace mbonnin
{
void my_struct(void);
}
void mbonnin::my_struct(void)
{
printf("standard function\n");
}
int main (int argc, char *argv[])
{
my_struct s;
s.a = 1;
s.b = 2;
printf("%d-%d\n", s.a, s.b);
mbonnin::my_struct();
return 0;
}
And by the way the struct in struct my_struct s; is redundant in C++.
warning: ‘void my_struct()’ hides constructor for ‘struct my_struct’
Any idea what this warning mean ?
It means that sometimes the warnings issued by the GNU compiler suite are a bit off. (Try omitting the semicolon after the close brace on the definition of struct my_struct. If you are using anything but a very recent version of g++ the error message will be a bit off.)
Something is being hidden here, but it is not the constructor for struct my_struct. What is being hidden is the name my_struct as a type identifier. You can see this in action if you remove the struct from the declaration of the variable s: Use my_struct s; instead of struct my_struct s; Without the contextual information offered by the struct keyword, the compiler now must interpret my_struct as a function name.