Equivalent to toString() in Eclipse for GDB debugging - c++

In Eclipse I can override the toString() method of an Object to pretty print it. This is especially useful because during a debug sessions as I can click on a variable and see the object in a human readable form.
Is there any kind of equivalent for C++ during a gdb session. I'm also open to any IDEs that can emulate this behavior.

In gdb, print command prints the contents of the variable. If you are using any IDE for C++, eg. Netbeans, Eclipse, VC++ then pointing on the variable shows the content.
EDIT: See if the below code is what you are looking for.
#include <string>
using std::string;
#define magic_string(a) #a
template<typename T>
class Object_C
{
private:
virtual string toString_Impl()
{
return magic_string(T);
}
public:
Object_C(void)
{
}
virtual ~Object_C(void)
{
}
string toString()
{
return toString_Impl();
}
};
class Base_C :
public Object_C<Base_C>
{
private:
string toString_Impl()
{
char str[80] = "";
sprintf_s(str, 79, "Base.x:%d\n", x_);
return string(str);
}
private:
int x_;
public:
Base_C(int x = 0) : x_(x) { }
~Base_C(void);
};
void ToStringDemo()
{
Base_C base;
cout << base.toString() << endl;
}

using visual Studio C++ instead?
[DebuggerDisplay("Count = {count}")]
class MyHashtable
{
public int count = 4;
}
https://learn.microsoft.com/en-us/dotnet/framework/debug-trace-profile/enhancing-debugging-with-the-debugger-display-attributes

Related

calling a struct member declared in a class

I am trying to place functions inside a struct which is part of a class (here named menu) so I can modify the struct inside of a dedicated setup cpp file (I am trying to do this so I can modify all of the functions I want in my application in a single source file instead of changing stuff in all of my cpp files):
// Menu.h
class menu
{
public:
menu();
struct pages
{
void print_page_1();
void print_page_2();
};
};
// Setup.cpp
struct menu::pages
{
void print_page_1()
{
// ...
}
void print_page_2()
{
// ...
}
};
Then I get an error when trying to call a function within my struct:
int main()
{
menu myMenu();
myMenu.pages.print_page_1(); // error: type name is not allowed
}
What does this error mean and how can I avoid it?
Thank you!
pages is the name of the struct, it's not an object. You need an object of type pages inside menu.
Otherwise, you can have static methods inside pages and call those without creating objects.
Example (live):
#include <iostream>
struct S
{
struct P
{
void print()
{
std::cout << "Hello from P!\n";
}
} p; // object of P
struct Q
{
static void print()
{
std::cout << "Hello from Q!\n";
}
};
};
int main()
{
S s;
s.p.print();
S::Q::print();
return 0;
}
Output:
Hello from P!
Hello from Q!
You need to declare a pages object in menu.
#include <iostream>
class menu
{
std::string p1 = "1";
std::string p2 = "2";
public:
struct pages
{
menu& m;
pages(menu &m):m(m){
}
void print_page_1();
void print_page_2();
} pages;
menu():pages(*this){
}
};
void menu::pages::print_page_1()
{
std::cout << m.p1;// ...
}
void menu::pages::print_page_2()
{
std::cout << m.p2;// ...
}
int main() {
menu myMenu;
myMenu.pages.print_page_1();
// your code goes here
return 0;
}

C++ code builds in CodeBlocks but not in Visual Studio 2015

I was given sample code in a C++ course I am taking. I can get it to build in CodeBlocks but not in Visual Studio 2015. In Visual Studio the main line "rename test3;" raises an error looking for a semicolon and the variable declaration in that line, "rename", is not highlighted in the default green for a type as it should be. Same for the next line. Therefore test3 and test4 come up as undefined. If I remove "#include <iostream>" "rename" turns to green in lines 33 and 34 but then the std include become undefined. Implementing "using namespace std" doesn't help either. I am attempting to get rid of "using namespace std" as it is not good coding practice from what I understand around here. I am missing a VS setting I think.
//#include <iostream> // original first two line
//using namespace std; //
#include <iostream>
#include <cstring> // I added this include
using std::cin; // I added the following using lines
using std::cout;
using std::endl;
class feature { // this class has a specific feature
private:
char data[16];
public:
feature() { strcpy(data, "default"); }
feature(char * in) { strcpy(data, in); } // error checks needed
void set(char * in) { strcpy(data, in); }
void out() { cout << data << endl; }
};
class rename : private feature {
public:
void reset(char * in) { set(in); }
void print() { out(); }
rename() : feature() {}
rename(char * in) : feature(in) {}
};
int main() {
feature test1;
feature test2("test2 data");
rename test3;
rename test4("test4 data");
test1.out();
test2.out();
test3.print();
test4.print();
}
The results should be:
default
test2 data
default
test4 data
default
test4 data
If I change back to the original first two lines the code does not work. If I rename "rename" to "rename1" then the code works.
#include <iostream>
using namespace std;
class feature { // this class has a specific feature
private:
char data[16];
public:
feature() { strcpy(data, "default"); }
feature(char * in) { strcpy(data, in); } // error checks needed
void set(char * in) { strcpy(data, in); }
void out() { cout << data << endl; }
};
class rename1 : private feature {
public:
void reset(char * in) { set(in); }
void print() { out(); }
rename1() : feature() {}
rename1(char * in) : feature(in) {}
};
int main() {
feature test1;
feature test2("test2 data");
rename1 test3;
rename1 test4("test4 data");
test1.out();
test2.out();
test3.print();
test4.print();
}
rename is a function that gets included by the header <cstring> in Visual Studio, which causes a conflict with the name of your class. You therefore need to change the name of your derived class. Visual Studio will probably also require you to change strcpy to strcpy_s (it may either give a Warning or Error otherwise).
Ideally you should avoid using C compatibility headers in new code you write (unless you absolutely need them), e.g.: in your example you should stick to std::string instead of char*

Pointer to a different instance.

How can such a code work correctly when the IWindow pointer clearly has an address to a ISheet class which has no method Say?
#include <iostream>
using namespace std;
class IWindow
{
private:
int p;
double f;
public:
void Say() { cout << "Say in IWindow"; }
};
class ISheet
{
public:
void foo() { cout << "ISheet::foo"; }
};
int main()
{
ISheet *sh = new ISheet();
int ptr = (int)sh;
IWindow *w = (IWindow*)ptr;
w->Say();
sh->foo();
return 0;
}
When compiled in Visual Studio 2015 it runs and executes with no problems, but I was expecting to get an error on line w->Say(). How is this possible?
It works by the grace of the almighty Undefined Behavior. Your functions don't try to access any data members of the containing class, they just write something to std::cout, which anyone can do.
What you've effectively done is
#include <iostream>
void IWindow_Say(void*)
{
std::cout << "Say in IWindow";
}
int main()
{
IWindow_Say(0xdeadbeef); // good luck with that pointer
}
You never used the pointer (which became this in your original example) so no side-effects were observed.

Accessing Public Class Function in Private Class Giving Error

class test
{
private:
class privateStruct
{
public:
int m;
privateStruct(int p){m=p;}
};
};
void ff()
{
test::privateStruct ps(4);
throw ps; //Does not work..
}
void main()
{
try
{
ff();
}
catch(...)
{
}
}
But the Following Code Works Why
class test
{
private:
class privateStruct
{
public:
int m;
privateStruct(int p){m=p;}
};
};
void ff()
{
throw test::privateStruct(4); //Work why
}
void main()
{
try
{
ff();
}
catch(...)
{
}
}
NOTE : I am using VC++ 6.
I need answer why the above code works.
Thanks in Advance :)
This is an old/known bug with Visual Studio 6.0. It ignores access specifiers when constructing temporaries. No fix is available.
Raising the warning level to 3 or higher (/W3) will cause the offending code to give a warning.
The code in your second example works because Visual C++ 6 is notorious for its horrible standards compliance.
It works by accident.
Even the second code snippet won't compile. privateStruct cannot be accessed in the function ff().

Observer design pattern in C++

Is the observer design pattern already defined in STL (Like the java.util.Observer and java.util.Observable in Java) ?
No, but Boost.Signals2 gives you something similar.
As far as my knowledge goes in C++, STL doesn't have an implementation for Observer pattern. There was a proposal for Signal/Slot for standard library in TR2 though.
There are plenty of libraries which provides implementation for Observer pattern Qt library being one of the pioneers. The boost library has an implementation (see Boost::Signals & Boost::Signals2).
The Poco C++ library has a neat implementation of the observer pattern (see NotificationCenter).
libsigc++, cpp-events are some of the other libraries that provide signal/slot implementations.
No it doesn't. The C++ STL is much smaller than Java's Standard Library. If you are looking for something to expand on the STL that is supported by almost everything, it would be worth taking a look at the Boost libraries. In this case you may want to look at Boost.Signals which provides a signal/slot model.
Here is a reference implementation (from Wikipedia).
#include <iostream>
#include <string>
#include <map>
#include <boost/foreach.hpp>
class SupervisedString;
class IObserver{
public:
virtual void handleEvent(const SupervisedString&) = 0;
};
class SupervisedString{ // Observable class
std::string _str;
std::map<IObserver* const, IObserver* const> _observers;
typedef std::map<IObserver* const, IObserver* const>::value_type item;
void _Notify(){
BOOST_FOREACH(item iter, _observers){
iter.second->handleEvent(*this);
}
}
public:
void add(IObserver& ref){
_observers.insert(item(&ref, &ref));
}
void remove(IObserver& ref){
_observers.erase(&ref);
}
const std::string& get() const{
return _str;
}
void reset(std::string str){
_str = str;
_Notify();
}
};
class Reflector: public IObserver{ // Prints the observed string into std::cout
public:
virtual void handleEvent(const SupervisedString& ref){
std::cout<<ref.get()<<std::endl;
}
};
class Counter: public IObserver{ // Prints the length of observed string into std::cout
virtual void handleEvent(const SupervisedString& ref){
std::cout<<"length = "<<ref.get().length()<<std::endl;
}
};
int main(){
SupervisedString str;
Reflector refl;
Counter cnt;
str.add(refl);
str.reset("Hello, World!");
std::cout<<std::endl;
str.remove(refl);
str.add (cnt);
str.reset("World, Hello!");
std::cout<<std::endl;
return 0;
}
#include <iostream>
#include <string>
#include <set>
using namespace std;
class Subject;
class Observer {
public:
virtual void update(Subject & subject) = 0;
};
// also knows as Observable in literature
class Subject
{
string state;
set<Observer*> observers;
public:
void attachObserver(Observer *o) { observers.insert(o); }
void detachObserver(Observer *o) { observers.erase(o); }
void notifyObservers()
{
for (auto &o : observers)
{
o->update(*this);
}
}
string getState() { return state; }
void changeState(const string & s)
{
state = s;
notifyObservers();
}
};
class ObserverImpl : public Observer
{
string state;
public:
void update(Subject & sbj) override
{
state = sbj.getState();
}
string getState() { return state; }
};
int main()
{
ObserverImpl a, b, c;
Subject subject;
subject.attachObserver(&a);
subject.attachObserver(&b);
subject.attachObserver(&c);
subject.changeState("Observer pattern");
cout << a.getState() << endl;
cout << b.getState() << endl;
cout << c.getState() << endl;
return 0;
}
please also see UML/flow diagrams http://codepatterns.ddns.net/
The Observer design pattern is not defined in the STL. You can refer to the "Gang of four" Design Patterns book or a Google search should provide enough details to implement it. If this question isn't answered soon, I'll post a quick example.
#include<iostream>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
class Customer;
class flipkart
{
vector<Customer*>list;
vector<Customer*>::iterator it;
public:
void Register(Customer *customer)
{
list.push_back(customer);
}
void unregister(Customer *customer)
{
list.erase(remove(list.begin(), list.end(),customer), list.end());
}
void notify(string item,float vprice);
};
class observer
{
public:
virtual void update(string item,float vprice)=0;
};
class Customer:public observer
{
string name;
public:
Customer(string n)
{
name=n;
}
void update(string item,float vprice)
{
cout<<"**Flipkart**updated price for "<<item<<" is:"<<vprice<<" Rupees only, request recieved by "<<name<<endl;
}
};
void flipkart::notify(string item,float vprice)
{
for(it=list.begin();it!=list.end();it++)
{
(*it)->update(item,vprice);
}
}
class product:public flipkart
{
public:
void change_price(string item,float vprice)
{
notify(item,vprice);
}
};
int main()
{
Customer customer1("Dhoni"),customer2("Yuvraj"),customer3("Kohli");
product LCD;
LCD.Register(&customer1);
LCD.Register(&customer2);
LCD.Register(&customer3);
LCD.change_price("LCD HD2 TV",12000);
LCD.unregister(&customer2);
cout<<"after unregisterng customer2:\n";
LCD.change_price("LCD HD2 TV",11500);
}