Link to home
Start Free TrialLog in
Avatar of farzanj
farzanjFlag for Canada

asked on

Differs in level of redirection

This is follow up for discussion in:

https://www.experts-exchange.com/questions/28019385/C-inheritance-with-pointers-to-array.html?anchorAnswerId=38852420#a38852420

This is just a pseudo example of my actual work.  Now there appears to be some difference because it compiles and the actual one has the following errror:

PmdsParser' differs in levels of indirection from 'std::string [14]'
1>  pmds_parser.cpp

This in this example would make it class B.  I wonder if you can guess it by looking at this analogous example or I can offer excerpts on your request.

You may also offer any more advice from the previous discussion.

#include<iostream>
#include<string>

using namespace std;

const int  num = 10;

string vals[num] = {"first", "second", "third", "fourth", "Fifth", "6th", "7th", "8th", "9th", "10th"};

class A
{
public:
	A(string* s1, string* s2, const int& n1) : n(n1)
	{
		//n  = n1;
		v1 = s1;
		v2 = s2;
	}
	void copy()
	{
		for(int i=0; i < n; i++)
		{
			v2[i] = v1[i];
		}
	}
protected:
	const int&    n;
	string* v1;
	string* v2;
};

class B : public A
{
public:
	B(string* s, int& n) : A(vals, s, n) // call base class constructor from initializer list
	{
	}
};


int main()
{
	const int COUNT = 10;
	string ans[COUNT];
    int n1 = num;
	B b(ans, n1);
	b.copy();
	for(int i=0; i < num; i++)
	{
		cout << ans[i] << endl;
	}
	cin.get();

	return 0;
}

Open in new window

SOLUTION
Avatar of ambience
ambience
Flag of Pakistan image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of farzanj

ASKER

Hi Sara,
To your comment in the last discussion.
Here's my design, I have a parser class which will have many sub classes.  Each of these sub classes will have a list of tokens that I need to pass, may be I should not store pointer instead the whole array, I don't know.  Then the client program uses these sub classes and sends lines to each parser subclass to be parsed according to their types.  I am initializing tokens in the sub classes as the parser is more generic.  Sub classes are specific to one kind of input and they will override some members of the parent class as well.  Once a parser is initialized, I do not want any noise of sending so many arrays in every call.  I just want to sent a single record that needs to be parsed.

The token arrays are used trillions of times and I want that access to be as fast as possible.  Theoretically, I think that keeping it in the stack and not using vector makes it faster.  Do you disagree?
Your example compiles just fine - could you post the actual code that is failing, or at least parts of it?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of farzanj

ASKER

I was able to resolve the earlier error but now there are linking errors.  If you go to the test.cpp file, you will see a comment.  If you follow that instruction, it would remove the compilation error but the linking errors still remain.

I need the explanation why this error went away and the reason/solution of linking errors.
EE.zip
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>>and then fill it with meaningful code

... and if that only would mean calling a base class' constructor (if there is one), e.g.

PmdsParser::PmdsParser(string* a, const int& n) : Parser(s,n) {}

Open in new window

Avatar of farzanj

ASKER

Hi JKR,
Sorry, I lost you.  In pmds_parser.cpp file, I do have implementation of parser.

PmdsParser::PmdsParser(string* r, const int& n)  : Parser(TOKENS, TERMS, r, REQUIREMENT, DIRECTIONS, n)
{
}

Open in new window


If you comment one line mentioned in the test.cpp file and uncomment the alternate, it even compiles but I get linking errors which don't to have any issue with the constructor rather my constant globals appear to be an issue.

And I could not send the VC++ project files as EE doesn't accept it.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Sorry, must have missed that - what exactly are the linker errors you are getting?
Avatar of farzanj

ASKER

These are the errors:
1>------ Build started: Project: parserproj, Configuration: Debug Win32 ------
1>  test.cpp
1>  pmds_parser.cpp
1>  parser.cpp
1>  Generating Code...
1>test.obj : error LNK2005: "bool * DIRECTIONS" (?DIRECTIONS@@3PA_NA) already defined in pmds_parser.obj
1>test.obj : error LNK2005: "bool * REQUIREMENT" (?REQUIREMENT@@3PA_NA) already defined in pmds_parser.obj
1>test.obj : error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > * TERMS" (?TERMS@@3PAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@A) already defined in pmds_parser.obj
1>test.obj : error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > * TOKENS" (?TOKENS@@3PAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@A) already defined in pmds_parser.obj
1>test.obj : error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > * FILTERS" (?FILTERS@@3PAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@A) already defined in pmds_parser.obj
1>C:\Users\fmufti\Desktop\C++Projects\EE\Debug\parserproj.exe : fatal error LNK1169: one or more multiply defined symbols found
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Ah, I see - you can fix that by using a construct similar to a header guard, e.g.

#ifndef CONSTANTS_DEFINED
const bool AND      = true;
const bool OR       = false;
const bool FORWARD  = true;
const bool REVERSE  = false;
const bool REQUIRED = true;
const bool OPTIONAL = false;
const string DELIM   = "\t";
#define CONSTANTS_DEFINED
#else
extern const bool AND ;
extern const bool OR;
extern const bool FORWARD;
extern const bool REVERSE;
extern const bool REQUIRED;
extern const bool OPTIONAL;
extern const string DELIM;
#endif

Open in new window

Avatar of farzanj

ASKER

Sorry, still the same.

I used the following:
#ifndef CONSTANT_DEFINED
#define CONSTANT_DEFINED
const int CAPTURE_COUNT = 13;
const int TOKEN_COUNT   = 14;
const int FILTER_COUNT  = 2;
bool DIRECTIONS[TOKEN_COUNT]  = {REVERSE, REVERSE, FORWARD, FORWARD, FORWARD, FORWARD, FORWARD,
                                               FORWARD, FORWARD, FORWARD, FORWARD, FORWARD, FORWARD};

bool REQUIREMENT[TOKEN_COUNT] = {REQUIRED, REQUIRED, REQUIRED, REQUIRED, REQUIRED, REQUIRED, 
	                                           OPTIONAL, OPTIONAL, OPTIONAL, OPTIONAL, OPTIONAL, OPTIONAL, OPTIONAL};

string TOKENS[TOKEN_COUNT]     = {" <", ">:", ":[", ":<", "LAYER =" ,"DEVICEPIN = ", "DOMAINNAME = ", "CONNECTION_TYPE = ",
                                      "ConnectionId = ", "DURATION(ms) = ", "MFH_KBytes = ", "MTH_KBytes = ", "MFH_PACKET_COUNT = ",
									  "MTH_PACKET_COUNT = "};

string TERMS[TOKEN_COUNT]      = {" ", "<", "]", ">", "", ",", ",", ",", ",", ",", ",", ",", ",", ">"};

string FILTERS[FILTER_COUNT]   = {"<INFO", "LAYER = IPPP"};

#else
extern const int CAPTURE_COUNT;
extern const int TOKEN_COUNT;
extern const int FILTER_COUNT;
extern bool DIRECTIONS[TOKEN_COUNT];

extern bool REQUIREMENT[TOKEN_COUNT];

extern string TOKENS[TOKEN_COUNT];

extern string TERMS[TOKEN_COUNT];

extern string FILTERS[FILTER_COUNT];
#endif

Open in new window


But still getting linking errors:
1>test.obj : error LNK2005: "bool * DIRECTIONS" (?DIRECTIONS@@3PA_NA) already defined in pmds_parser.obj
1>test.obj : error LNK2005: "bool * REQUIREMENT" (?REQUIREMENT@@3PA_NA) already defined in pmds_parser.obj
1>test.obj : error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > * TERMS" (?TERMS@@3PAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@A) already defined in pmds_parser.obj
1>test.obj : error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > * TOKENS" (?TOKENS@@3PAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@A) already defined in pmds_parser.obj
1>test.obj : error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > * FILTERS" (?FILTERS@@3PAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@A) already defined in pmds_parser.obj
1>C:\Users\fmufti\Desktop\C++Projects\EE\Debug\parserproj.exe : fatal error LNK1169: one or more multiply defined symbols found
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of farzanj

ASKER

Ok, linking errors are gone by simply moving the constant declarations from pmds_parser.h to pmds_parser.cpp file.

One more issue is that I cannot declare a default constructor because apparently
const int&     token_count
 has to be initialized for the class to get initialized and I cannot do that in the default constructor because I need the value of token count from the client (test.cpp).  

So, MUST references always be initialized for objects?  How do I take care of this issue?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
yes the new standard c11 will be more powerful. i nevertheless  would suggest you to use the current standard which was released 1998 and therefore is used by most of current applications and you could draw on the experiences of many experts. the new standard will be based on the current standard (and i would guess it is better to do the first step before the second :) )

Sara
Avatar of farzanj

ASKER

Thank you all for your time.  Sara, I would definitely benchmark your type of solution.