Method overloading with const/non-const variants (was: Re: KDE/kdelibs/kdecore)

Richard Dale rdale at foton.es
Tue Jul 8 14:20:08 BST 2008


On Tuesday 08 July 2008 13:55:23 Thiago Macieira wrote:
> Friedrich W. H. Kossebau wrote:
> >What about overloaded methods? Hm, running the test from below shows me
> > that I have been thinking wrong for many years, duh. So the compiler
> > chooses the variant by the constness of the object? I thought it takes
> > all possible variants and then narrows the selection further by the
> > LHS, going for constness if possible?
> >
> >Is this defined by the C++ specs? Does anyone know the rationale behind
> > this?
>
> Yes, this is defined by the C++ spec. When you call a function foo(...)
> with a set of parameters, the compiler will try to find all instances
> of "foo" in the class and see which one fits best to the parameters you
> gave.
>
> I don't know the exact rules for type promotion and demotion, but there
> are cases where it becomes ambiguous. If it does, then the compiler will
> print an error and ask you what to do.
>
> An interesting thing about the search is when it happens to template
> types: no promotion or demotion is applied. The compiler searches only
> for the exact match.
>
> The compiler always selects the less constraining overload of a function
> given its CV-qualifiers (CV = const, volatile). If you have the following
> four overloads of foo():
>
> 	void foo();
> 	void foo() const;
> 	void foo() volatile;
> 	void foo() const volatile;
>
> The CV qualifier to a function applies to the this pointer implicit
> parameter. So you can think of that as:
>
> 	void foo(Class *this);
> 	void foo(const Class *this);
> 	void foo(volatile Class *this);
> 	void foo(const volatile Class *this);
>
> So now you can apply the same rules as parameter overloading. That's why
> the compiler chooses the less constraining one. That's also why
> the "const" variants may be called in any circumstances, but the
> non-const ones cannot be called with a const object.

I think it is great that people can understand these rules, and manage to 
write code where they understand how it works. But personally I wish we 
didn't use const overloading in KDE libs unless absolutely necessary. There 
are no other languages apart from C++, that use const overloading as far as I 
know, and it makes it awkward for language bindings.

Here are the const/non-const method overloads in the kde headers, with the 
comments extracted. Most of them do the same thing according to the comments. 
Only two or  three actually have different behaviour. I would prefer that we 
deprecate one of the const or non-const methods that are the same at least.

-- Richard


   /**
     * Returns an object for the named subgroup.
     *
     * @param group the group to open. Pass a null string on to the KConfig
     *   object to obtain a handle on the root group.
     * @return The list of groups.
     **/
    KConfigGroup group(const QByteArray &group);
    KConfigGroup group(const QString &group);
    KConfigGroup group(const char *group);

    /**
     * @overload
     **/
    const KConfigGroup group(const QByteArray &group) const;
    const KConfigGroup group(const QString &group) const;
    const KConfigGroup group(const char *group) const;

    /**
     * Return the config object that this group belongs to.
     */
    KConfig* config();
    const KConfig* config() const;


  /**
   * Return the @ref KConfig object used for reading and writing the settings.
   */
  KConfig *config();

  /**
   * Return the @ref KConfig object used for reading and writing the settings.
   */
  const KConfig *config() const;

/**
   * Sets the desktop action group.
   * @param group the new action group
   */
  KConfigGroup actionGroup(const QString &group);

  const KConfigGroup actionGroup(const QString &group) const;


   /**
     * Returns the context menu associated with this menu
     * The data property of all actions inserted into the context menu is 
modified
     * all the time to point to the action and menu it has been shown for
     */
    QMenu* contextMenu();

    /**
     * Returns the context menu associated with this menu
     */
    const QMenu* contextMenu() const;


    /**
     * Returns the page widget of the dialog or 0 if no page widget is set.
     */
    KPageWidget *pageWidget();

    /**
     * Returns the page widget of the dialog or 0 if no page widget is set.
     */
    const KPageWidget *pageWidget() const;



    /**
     * @return the axis of the specified @p type, or 0 if no axis has been 
set.
     * @sa Axis
     */
    KPlotAxis* axis( Axis type );

    /**
     * @return the axis of the specified @p type, or 0 if no axis has been 
set.
     * @sa Axis
     */
    const KPlotAxis* axis( Axis type ) const;


        /**
         * Returns the QProgressBar used in this dialog.
         * To set the number of steps or other progress bar related
         * settings, access the QProgressBar object directly via this method.
         */
        QProgressBar *progressBar();

        /**
         * Returns the QProgressBar used in this dialog.
         * To set the number of steps or other progress bar related
         * settings, access the QProgressBar object directly via this method.
         */
        const QProgressBar *progressBar() const;






More information about the kde-core-devel mailing list