friend class across namespaces & different .H files - c++

I'm trying to make the following compile under VS 2008 SP1 C++ project, but the friend class statement doesn't seem to have any effect. (See error message in the last code snippet.)
What am I doing wrong with the friend definition?
// EncryptionTypes.h file
#pragma once
//#include "Encryption.h" //adding this line doesn't help
using namespace crypto;
struct FILE_DATA_CACHE{
FILE_DATA_CACHE()
{
};
~FILE_DATA_CACHE()
{
}
friend class CEncryption;
private:
bool _isIndexFileUsed()
{
return bResult;
}
};
then:
// Encryption.h
#pragma once
#include "EncryptionTypes.h"
namespace crypto
{
class CEncryption
{
public:
CEncryption(void);
~CEncryption(void);
private:
BOOL _openFile();
private:
FILE_DATA_CACHE gFData;
};
};
and lastly:
// Encryption.cpp
#include "StdAfx.h"
#include "Encryption.h"
namespace crypto
{
CEncryption::CEncryption(void)
{
}
CEncryption::~CEncryption(void)
{
}
void CEncryption::_openFile()
{
//The line below generates this error:
//1>.\Encryption.cpp(176) : error C2248: 'FILE_DATA_CACHE::_isIndexFileUsed' : cannot access private member declared in class 'FILE_DATA_CACHE'
//1> c:\users\blah-blah\EncryptionTypes.h(621) : see declaration of 'FILE_DATA_CACHE::_isIndexFileUsed'
//1> c:\users\blah-blah\EncryptionTypes.h(544) : see declaration of 'FILE_DATA_CACHE'
gFData._isIndexFileUsed();
}
};

You have a circular dependency problem.
Encryption.h needs FILE_DATA_CACHE, which is defined in EncryptionTypes.h.
EncryptionType.h needs CEncryption, which is defined in Encryption.h.
Fortunately, you can get by with using a forward declaration of CEncryption in EncryptionType.h.
Modify EncryptionType.h to:
// EncryptionTypes.h file
#pragma once
// Can't #include Encryption.h. That will lead to circular
// #includes.
namespace crypto
{
// Forward declaration of crypto::CEncryption
class CEncryption;
}
struct FILE_DATA_CACHE{
FILE_DATA_CACHE()
{
};
~FILE_DATA_CACHE()
{
}
friend class crypto::CEncryption;
private:
bool _isIndexFileUsed()
{
return bResult;
}
};

Related

initializing a static (non-constant) variable of a class.

I have TestMethods.h
#pragma once
// strings and c-strings
#include <iostream>
#include <cstring>
#include <string>
class TestMethods
{
private:
static int nextNodeID;
// I tried the following line instead ...it says the in-class initializer must be constant ... but this is not a constant...it needs to increment.
//static int nextNodeID = 0;
int nodeID;
std::string fnPFRfile; // Name of location data file for this node.
public:
TestMethods();
~TestMethods();
int currentNodeID();
};
// Initialize the nextNodeID
int TestMethods::nextNodeID = 0;
// I tried this down here ... it says the variable is multiply defined.
I have TestMethods.cpp
#include "stdafx.h"
#include "TestMethods.h"
TestMethods::TestMethods()
{
nodeID = nextNodeID;
++nextNodeID;
}
TestMethods::~TestMethods()
{
}
int TestMethods::currentNodeID()
{
return nextNodeID;
}
I've looked at this example here: Unique id of class instance
It looks almost identical to mine. I tried both the top solutions. Neither works for me. Obviously I'm missing something. Can anyone point out what it is?
You need to move the definition of TestMethods::nextNodeID into the cpp file. If you have it in the header file then every file that includes the header will get it defined in them leading to multiple defenitions.
If you have C++17 support you can use the inline keyword to declare the static variable in the class like
class ExampleClass {
private:
inline static int counter = 0;
public:
ExampleClass() {
++counter;
}
};

How do I define the same named structure in more than one class?

I've got multiple classes from multiple engineers which I am using and they have the same named structures in the classes. From this I get the error "'struct' type redefinition". How do I get around this?
Example:
// Eng1Class.h
#pragma once
struct Eng1And2SameName
{
unsigned int bottle;
};
class Eng1Class
{
public:
Eng1Class();
~Eng1Class();
};
.
// Eng2Class.h
#pragma once
struct Eng1And2SameName
{
float x, y;
};
class Eng2Class
{
public:
Eng2Class();
~Eng2Class();
};
.
// Main Program
#include "stdafx.h"
#include "Eng1Class.h"
#include "Eng2Class.h"
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
Error: error C2011: 'Eng1And2SameName' : 'struct' type redefinition
According to this Compile error "'struct' type redefinition" although it's the first definition for it the #pragma once should fix the issues, but I still see the error. Any insights you can provide?
No, #pragma once prevents the header files from being included more than once - each is included once -> redefinition.
they have the same named structures in the classes
*header files
The're not defined inside the classes (nested), but they could be:
class Eng1Class
{
public:
struct Eng1And2SameName
{
unsigned int bottle;
};
Eng1Class();
~Eng1Class();
};
Or you could enclose the contents of those headers into two differently named namespaces.
Defining a namespace would help
For example as you said error with same struct definition in same namescope .
Reports error
You can do it by defining namesapce
#include<iostream>
using namespace std;
namespace Eng1 {
struct Eng1And2SameName
{
unsigned int bottle;
};
}
namespace Eng2
{
struct Eng1And2SameName
{
float x, y;
};
}
int main()
{
Eng1::Eng1And2SameName a;
Eng2::Eng1And2SameName b;
return 0;
}
Usually engineers working on the same product are coordinated somehow, at least they will use a common source code repository and a common build. Hence, conflicts should have come up earlier.
"uncoordinated" engineers may happen when they work on different products, and if so, each product could have its own namespace. Thereby, you can combine the products without having conflicts:
// in a header:
namespace Eng1Class {
struct Eng1And2SameName
{
unsigned int bottle;
};
class EngClass
{
public:
EngClass();
~EngClass();
};
}
// in the cpp-file
Eng1Class::EngClass::EngClass() {
cout << "hello, Class 1";
}
// in another (or even the same) header
namespace Eng2Class {
struct Eng1And2SameName
{
float x, y;
};
class EngClass
{
public:
EngClass();
~EngClass();
};
}
// in another (or even the same) cpp-file
Eng2Class::EngClass::EngClass() {
cout << "hello, Class 2";
}

Include issue: 'multiple definition', 'first defined here'

I have three files:
main.cpp
MyClass.cpp
MyClass.hpp
I have a library header file, "testLib.hpp", that I want to include in MyClass.hpp so that I can have one of testLib's objects be a class attribute.
I include MyClass.hpp in MyClass.cpp and in main.cpp. When attempting to compile the project, I get the following errors
MyClass.cpp multiple definition of 'testLib::testLib::function1()
obj/Release/main.o:main.cpp first defined here
MyClass.cpp multiple definition of 'testLib::testLib::function2()
obj/Release/main.o:main.cpp first defined here
and so on.
Both main.cpp and MyClass.cpp include MyClass.hpp (which includes testLib.hpp). Judging by the error, it looks like MyClass.cpp is attempting to include the library functions after they've already been included by main.cpp. However, I have include guards present in MyClass.hpp so I don't understand how it's trying to include MyClass.hpp twice.
Here's the code:
MyClass.hpp
#ifndef THIS_HEADER_H
#define THIS_HEADER_H
#include <stdint.h>
#include <iostream>
#include "testLib/testLib.hpp"
class MyClass
{
public:
void test();
int foo;
private:
uint32_t bar;
//I want to include an object from the library as part of this class
//TestLib::Device device;
};
#endif
MyClass.cpp
#include <stdio.h>
#include "MyClass.hpp"
void MyClass::test()
{
}
main.cpp
#include <iostream>
#include "MyClass.hpp"
using namespace std;
int main()
{
cout << "Hello world!" << endl;
return 0;
}
Any help would be greatly appreciated!
EDIT
I tried to hide the actual filenames to make the question more general and clear, but it seems like the problem might be resulting from 'testLib.hpp', which I did not write. That file is actually the following "sweep.hpp" file. I got the 'multiple definition of/first defined here' errors for each of the public functions in this file:
sweep.hpp
#ifndef SWEEP_DC649F4E94D3_HPP
#define SWEEP_DC649F4E94D3_HPP
/*
* C++ Wrapper around the low-level primitives.
* Automatically handles resource management.
*
* sweep::sweep - device to interact with
* sweep::scan - a full scan returned by the device
* sweep::sample - a single sample in a full scan
*
* On error sweep::device_error gets thrown.
*/
#include <cstdint>
#include <memory>
#include <stdexcept>
#include <vector>
#include <sweep/sweep.h>
namespace sweep {
// Error reporting
struct device_error final : std::runtime_error {
using base = std::runtime_error;
using base::base;
};
// Interface
struct sample {
const std::int32_t angle;
const std::int32_t distance;
const std::int32_t signal_strength;
};
struct scan {
std::vector<sample> samples;
};
class sweep {
public:
sweep(const char* port);
sweep(const char* port, std::int32_t bitrate);
void start_scanning();
void stop_scanning();
bool get_motor_ready();
std::int32_t get_motor_speed();
void set_motor_speed(std::int32_t speed);
std::int32_t get_sample_rate();
void set_sample_rate(std::int32_t speed);
scan get_scan();
void reset();
private:
std::unique_ptr<::sweep_device, decltype(&::sweep_device_destruct)> device;
};
// Implementation
namespace detail {
struct error_to_exception {
operator ::sweep_error_s*() { return &error; }
~error_to_exception() noexcept(false) {
if (error) {
device_error e{::sweep_error_message(error)};
::sweep_error_destruct(error);
throw e;
}
}
::sweep_error_s error = nullptr;
};
}
sweep::sweep(const char* port)
: device{::sweep_device_construct_simple(port, detail::error_to_exception{}), &::sweep_device_destruct} {}
sweep::sweep(const char* port, std::int32_t bitrate)
: device{::sweep_device_construct(port, bitrate, detail::error_to_exception{}), &::sweep_device_destruct} {}
void sweep::start_scanning() { ::sweep_device_start_scanning(device.get(), detail::error_to_exception{}); }
void sweep::stop_scanning() { ::sweep_device_stop_scanning(device.get(), detail::error_to_exception{}); }
bool sweep::get_motor_ready() { return ::sweep_device_get_motor_ready(device.get(), detail::error_to_exception{}); }
std::int32_t sweep::get_motor_speed() { return ::sweep_device_get_motor_speed(device.get(), detail::error_to_exception{}); }
void sweep::set_motor_speed(std::int32_t speed) {
::sweep_device_set_motor_speed(device.get(), speed, detail::error_to_exception{});
}
std::int32_t sweep::get_sample_rate() { return ::sweep_device_get_sample_rate(device.get(), detail::error_to_exception{}); }
void sweep::set_sample_rate(std::int32_t rate) {
::sweep_device_set_sample_rate(device.get(), rate, detail::error_to_exception{});
}
scan sweep::get_scan() {
using scan_owner = std::unique_ptr<::sweep_scan, decltype(&::sweep_scan_destruct)>;
scan_owner releasing_scan{::sweep_device_get_scan(device.get(), detail::error_to_exception{}), &::sweep_scan_destruct};
auto num_samples = ::sweep_scan_get_number_of_samples(releasing_scan.get());
scan result;
result.samples.reserve(num_samples);
for (std::int32_t n = 0; n < num_samples; ++n) {
auto angle = ::sweep_scan_get_angle(releasing_scan.get(), n);
auto distance = ::sweep_scan_get_distance(releasing_scan.get(), n);
auto signal = ::sweep_scan_get_signal_strength(releasing_scan.get(), n);
result.samples.push_back(sample{angle, distance, signal});
}
return result;
}
void sweep::reset() { ::sweep_device_reset(device.get(), detail::error_to_exception{}); }
} // ns
#endif
A simplified version of your problem:
buggy.hpp
int function() { return 0; }
main.cpp
#include "buggy.hpp"
int main() { return 0; }
other.cpp
#include "buggy.hpp"
The problem is that buggy.hpp is defining function, not just declaring. Once the header inclusion is expanded, that means function is declared in both main.cpp and other.cpp - and that is not allowed.
The fix is to declare function as inline which allows the function to be declared in multiple translation units.
inline int function() { return 0; }
In fact, allowing multiple definitions is the only meaning of inline to the C++ standard. Compilers may treat it as a hint that the function body may be expanded inline. Good ones won't; they are better at making that sort of decision that programmers).

Compile time "null" using forward declaration?

I'm facing a problem using forward declaration, and I don't know how to fix it. Here's my files:
BubblePlug.h
#ifndef _BUBBLEPLUG_
#define _BUBBLEPLUG_
#include "IPlug_include_in_plug_hdr.h"
#include "resource.h"
#include "IControl.h"
class IPianoRoll;
class IMidiEngine;
class BubblePlug: public IPlug
{
private:
public:
IMidiEngine *pMidiEngine;
IPianoRoll *pPianoRoll;
BubblePlug(IPlugInstanceInfo instanceInfo);
~BubblePlug();
};
#endif // !_BUBBLEPLUG_
BubblePlug.cpp
#include "BubblePlug.h"
#include "IPlug_include_in_plug_src.h"
#include "IPianoRoll.h"
#include "IMidiEngine.h"
BubblePlug::BubblePlug(IPlugInstanceInfo instanceInfo) : IPLUG_CTOR(10, 1, instanceInfo) {
pPianoRoll = new IPianoRoll(this, 8, 8);
pMidiEngine = new IMidiEngine(this);
}
BubblePlug::~BubblePlug() {
delete pPianoRoll;
delete pMidiEngine;
}
IPianoRoll.h
#ifndef _IPIANOROLL_
#define _IPIANOROLL_
#include "IMidiEngine.h"
class IPianoRoll : public IControl
{
private:
BubblePlug *pBubblePlug;
public:
IPianoRoll(BubblePlug *bubbleplug, int x, int y) : IControl(bubbleplug, IRECT(x, y, x + 10, y + 10)), pBubblePlug(bubbleplug) {
}
~IPianoRoll() {
};
bool Draw(IGraphics *pGraphics) {
return true;
}
void Random(bool onlyScore = false) {
pBubblePlug->pMidiEngine->Init();
}
void Start() {
}
};
#endif // !_IPIANOROLL_
IMidiEngine.h
#ifndef _IMIDIENGINE_
#define _IMIDIENGINE_
class IMidiEngine
{
private:
BubblePlug *pBubblePlug;
public:
IMidiEngine(BubblePlug *bubbleplug) : pBubblePlug(bubbleplug) {
}
~IMidiEngine() {
};
void Init(bool randomScore = true) {
pSamplwhk->pPianoRoll->Start();
}
};
#endif // !_IMIDIENGINE_
when I compile, it says around pSamplwhk->pPianoRoll->Start();:
use of undefined type 'IPianoRoll'
left of '->Start' must point to class/struct/union/generic type
VS2015 find each element writing the code (I've no problem), it happens only when I compile (Build).
Why? I pass BubblePlug and I do forward of both IPianoRoll and IMidiEngine, including them in order (on BubblePlug.cpp).
IMidiEngine should know everythings about IPianoRoll (which it is included first).
At least, I should have problem at "runtime", why at compile?
Can you help me to understand the problem and how to fix it? Thanks.
IPianoRoll.h includes IMidiEngine.h, so no matter in which order you include the two files, the definition of IPianoRoll will always come after the init function where it is being used.
One way to avoid this is to move the body of the init function into a separate .cpp file:
In IMidiEngine.h:
void Init(bool randomScore=true);
In IMidiEngine.cpp:
void IMidiEngine::Init(bool randomScore) {
pSamplwhk->pPianoRoll->Start();
}

What does "void-value is not ignored" error mean and how to remove it?

I try to compile the following code:
#include <cppunit/extensions/HelperMacros.h>
#include "tested.h"
class TestTested : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(TestTested);
CPPUNIT_TEST(check_value);
CPPUNIT_TEST_SUITE_END();
public:
void check_value();
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestTested);
void TestTested::check_value() {
tested t(3);
int expected_val = t.getValue(); // <----- Line 18.
CPPUNIT_ASSERT_EQUAL(7, expected_val);
}
As a result I get:
testing.cpp:18:32: Error: void-value is not ignored where it should be
EDDIT
To make the example complete I post the code of the tested.h and tested.cpp:
tested.h
#include <iostream>
using namespace std;
class tested {
private:
int x;
public:
tested(int int_x);
void getValue();
};
tested.cpp
#include <iostream>
using namespace std;
tested::tested(int x_inp) {
x = x_inp;
}
int tested::getValue() {
return x;
}
you declare void getValue(); in the class tested.. change to int getValue();.
A void function cannot return a value.
You are getting a value of int from the API getValue(), hence it should return an int.
Your class definition doesn't match the implementation:
In your header you've declared it in the following way (as an aside, you might want to look into some naming conventions).
class tested {
private:
int x;
public:
tested(int int_x);
void getValue();
};
You've declared getValue() as void, i.e no return. Doesn't make much sense for a getter to return nothing, does it?
However, in the .cpp file you've implemented getValue() like so:
int tested::getValue() {
return x;
}
You need to update the getValue() method signature in the header type so that its return type matches the implementation (int).