element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Code Exchange
  • Technologies
  • More
Code Exchange
Blog C++ classes and operators
  • Blog
  • Forum
  • Documents
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Code Exchange to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 9 Mar 2025 7:23 PM Date Created
  • Views 554 views
  • Likes 5 likes
  • Comments 3 comments
  • operator
  • c++
Related
Recommended

C++ classes and operators

Jan Cumps
Jan Cumps
9 Mar 2025

This is a "classic C++" post, something that's been part of the language since conception: How to use an operator in your class design.

I developed a callback class. Your "gizmo that needs to callback something" would hold an instance of that class (an object). And you 'd assign some function to that object.

Callback<int> cb;
cb.set([]() -> void {
    start_video();
});

When the time is ripe (usually an event: an interrupt, a mouse click, UART data arrived, ...) you ask the callback class to execute that function. In this blog, I'm pretending that I'm a button, and someone clicked me. The effect should be that the start_video() callback gets executed.

In my original design, you reacted on that by calling the callback class call() method:

bool button1::clicked() {
    cb.call();
}

This would execute the start_video(). 

However, in C++ there is a standard way to indicate that something is a call and that you "execute the object" : the operator (). Similar to the operator +, that indicates that you want to add. I want that my class follows that paradigm.

This is how I want that a call should look like:

button1::clicked() {
    cb();
}

It again should call start_video(). Like the originall call() method did.

Implementing this isn't hard. In my Callback template class, I just had to replace call() by operator ():

class Callback {
public:
	// ...

	inline void operator()() {
	    // call the registered callback
	}
	
	// ...

};

in reality, my class is template driven, and will accept callbacks with any type / count of parameters. I've removed that for blogging simplicity.

Opinions on this topic may vary. I think that operator() indicates perfectly that you want the callback class to execute the callback handler. Let me know if you have a different preference.

  • Sign in to reply
Parents
  • Jan Cumps
    Jan Cumps 5 months ago

    Here is how I used this in Raspberry Pico code, where I use a callback when i need data from UART:

    callbackmanager::Callback<void, std::string&> reader;
    
    reader.set([](std::string& s) -> void { read(s); });
    // read is a Pico function that gets all available data from the controller's UART buffer.
    // it stores the results in the std::string tht's passed to it as a reference.

    In my business logic, that doesn't know anything about Pico or UART, I invoke a read by calling that callback:

    // In my business logic
    
    void mybusinessclass::read(std::string& s) {
        reader(s);
    }

    The callback class will call that read() function we set earlier, to get the data from the UART, and put it in std::string s.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • Jan Cumps
    Jan Cumps 5 months ago

    Here is how I used this in Raspberry Pico code, where I use a callback when i need data from UART:

    callbackmanager::Callback<void, std::string&> reader;
    
    reader.set([](std::string& s) -> void { read(s); });
    // read is a Pico function that gets all available data from the controller's UART buffer.
    // it stores the results in the std::string tht's passed to it as a reference.

    In my business logic, that doesn't know anything about Pico or UART, I invoke a read by calling that callback:

    // In my business logic
    
    void mybusinessclass::read(std::string& s) {
        reader(s);
    }

    The callback class will call that read() function we set earlier, to get the data from the UART, and put it in std::string s.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
  • Jan Cumps
    Jan Cumps 5 months ago in reply to Jan Cumps

    I've used explicit types in the code above,

    reader.set([](std::string& s) -> void { read(s); });

    but you can also use auto:

    reader.set([](auto& s) { read(s); });

    Both constructs are identical, and enforce the same strong type checks. auto is a useful way to (amongst other things) type less.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps 5 months ago in reply to Jan Cumps

    If you are into design patterns: this is dependency injection.

    Instead of learning my business logic how to read UART on a Raspberry Pico, I insert a function that knows how to do that.

    The only contract is that both have to agree upon, is the signature of that function, and what each parameter does (in this case: that the UART data "will be" / "has to be" placed in the string parameter.

    If I want to use this on an other platform (Arduino, Pi, ...) the business logic doesn't need changes. I just have to take care that I write an Arduino / Pi function that can read from UART and place that info in the s parameter. And set that function in the callback manager.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube