It has nothing do with grep, but with your current shell. The shell expands *.cpp to all the cpp file names in your current directory before running the grep command. Since it can't find any filenames, the glob *.cpp is left unexpanded by the shell. The grep command tries to see this is a file, but cribs that it is not a real file.
You have couple of options, use find
find . -type f -name "*.cpp" -exec grep -r zlib {} +
or if you are using a bash shell, set a nullglob option to stop returning un-expanded glob as a valid result. The (..) is to make the extended shell option temporary and not make it persistent in the shell. The reason to have the --include=*.cpp option is, with the option set, if the glob expansion fails *.cpp becomes empty and your command becomes grep -r zlib which means search in entire sub-directory below.
( shopt -s nullglob; grep -r --include=*.cpp zlib . ; )
Another variant that doesn't include the --include option of grep but using the globstar that allows recursive glob expansion in sub-directories
( shopt -s nullglob globstar; grep -rH zlib **/*.cpp ; )
Remember the --include= and -H are GNU grep options and not POSIX compatiable
grep: illegal option -- r, better usefindtigether withgrep...